Document number conversion (#5208)
* :memo: document number conversion
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* :construction_worker: fix CI
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
---------
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 07a024a..da5ede9 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -114,7 +114,7 @@
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure
ci_module_cpp20:
- runs-on: windows-latest
+ runs-on: windows-2022
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Run CMake (Debug)
diff --git a/docs/mkdocs/docs/api/basic_json/get.md b/docs/mkdocs/docs/api/basic_json/get.md
index 96fc221..68a4fa7 100644
--- a/docs/mkdocs/docs/api/basic_json/get.md
+++ b/docs/mkdocs/docs/api/basic_json/get.md
@@ -90,10 +90,25 @@
## Notes
-!!! danger "Undefined behavior"
+!!! danger "Undefined behavior for pointers"
Writing data to the pointee (overload 3) of the result yields an undefined state.
+!!! danger "Undefined behavior for numeric conversions"
+
+ Conversions between numeric types are performed by the corresponding
+ `from_json()` implementation using the target C++ type. When converting
+ between numeric types, the library does not check whether the source
+ value is representable by the target type.
+
+ If the source value is outside the range of the target type, the behavior
+ is the same as the corresponding C++ conversion. In particular, converting
+ a floating-point value to an integer type that cannot represent the value
+ results in undefined behavior.
+
+ See [Number conversion](../../features/types/number_handling.md#number-conversion)
+ for more information.
+
## Examples
??? example
diff --git a/docs/mkdocs/docs/api/basic_json/sax_parse.md b/docs/mkdocs/docs/api/basic_json/sax_parse.md
index 530c6f8..94e9d54 100644
--- a/docs/mkdocs/docs/api/basic_json/sax_parse.md
+++ b/docs/mkdocs/docs/api/basic_json/sax_parse.md
@@ -92,7 +92,6 @@
- Throws [`parse_error.102`](../../home/exceptions.md#jsonexceptionparse_error102) if `to_unicode` fails or surrogate
error.
- Throws [`parse_error.103`](../../home/exceptions.md#jsonexceptionparse_error103) if `to_unicode` fails.
-- Throws [`other_error.502`](../../home/exceptions.md#jsonexceptionother_error502) if `sax` is a null pointer.
## Complexity
@@ -125,7 +124,6 @@
- Added in version 3.2.0.
- Ignoring comments via `ignore_comments` added in version 3.9.0.
- Added `ignore_trailing_commas` in version 3.12.1.
-- Added `json.exception.other_error.502` exception in version 3.12.1.
!!! warning "Deprecation"
diff --git a/docs/mkdocs/docs/features/types/number_handling.md b/docs/mkdocs/docs/features/types/number_handling.md
index 9102376..a02c1d3 100644
--- a/docs/mkdocs/docs/features/types/number_handling.md
+++ b/docs/mkdocs/docs/features/types/number_handling.md
@@ -243,6 +243,19 @@
Note the last line with throw a [`json.exception.type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302)
exception if `jd` is not a numerical type, for instance a string.
+ Numeric conversions are performed according to the corresponding C++ conversion rules. The library does not perform
+ range checks when converting between numeric types.
+
+ In particular, conversions from floating-point values to integer types, or conversions to integer types with a
+ smaller range than the stored value, may produce implementation-defined or undefined behavior if the source value
+ cannot be represented by the target type.
+
+ Applications requiring checked conversions should inspect the stored number type with
+ [`is_number_float()`](../../api/basic_json/is_number_float.md),
+ [`is_number_integer()`](../../api/basic_json/is_number_integer.md),
+ [`is_number_unsigned()`](../../api/basic_json/is_number_unsigned.md), or
+ [`type()`](../../api/basic_json/type.md), and perform explicit range checks before converting to a narrower type.
+
The rationale is twofold:
1. JSON does not define a number type or precision (see above).
diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml
index c374926..8168bd4 100644
--- a/docs/mkdocs/mkdocs.yml
+++ b/docs/mkdocs/mkdocs.yml
@@ -270,6 +270,7 @@
- macros:
- 'Overview': api/macros/index.md
- 'JSON_ASSERT': api/macros/json_assert.md
+ - 'JSON_BRACE_INIT_COPY_SEMANTICS': api/macros/json_brace_init_copy_semantics.md
- 'JSON_CATCH_USER, JSON_THROW_USER, JSON_TRY_USER': api/macros/json_throw_user.md
- 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md
- 'JSON_DIAGNOSTIC_POSITIONS': api/macros/json_diagnostic_positions.md
diff --git a/tests/src/unit-serialization.cpp b/tests/src/unit-serialization.cpp
index c0f2a8e..f55ed84 100644
--- a/tests/src/unit-serialization.cpp
+++ b/tests/src/unit-serialization.cpp
@@ -311,14 +311,16 @@
SECTION("round-trip dump/parse")
{
constexpr std::array<long double, 13> values =
- {{
- 0.0L, -0.0L, 1.0L, -1.0L,
- 0.5L, -0.5L, 1.5L, -2.25L,
- 1.23e45L, 1.23e-45L,
- (std::numeric_limits<long double>::min)(),
- std::numeric_limits<long double>::lowest(),
- (std::numeric_limits<long double>::max)()
- }};
+ {
+ {
+ 0.0L, -0.0L, 1.0L, -1.0L,
+ 0.5L, -0.5L, 1.5L, -2.25L,
+ 1.23e45L, 1.23e-45L,
+ (std::numeric_limits<long double>::min)(),
+ std::numeric_limits<long double>::lowest(),
+ (std::numeric_limits<long double>::max)()
+ }
+ };
for (long double v : values)
{