mirror of
https://github.com/nlohmann/json.git
synced 2026-07-10 04:25:11 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 282f84cc8e |
@@ -4,8 +4,6 @@ updates:
|
|||||||
directory: /
|
directory: /
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
|
||||||
default-days: 7
|
|
||||||
groups:
|
groups:
|
||||||
codeql-action:
|
codeql-action:
|
||||||
patterns:
|
patterns:
|
||||||
@@ -15,33 +13,23 @@ updates:
|
|||||||
directory: /docs/mkdocs
|
directory: /docs/mkdocs
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
|
||||||
default-days: 7
|
|
||||||
|
|
||||||
- package-ecosystem: pip
|
- package-ecosystem: pip
|
||||||
directory: /tools/astyle
|
directory: /tools/astyle
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
|
||||||
default-days: 7
|
|
||||||
|
|
||||||
- package-ecosystem: pip
|
- package-ecosystem: pip
|
||||||
directory: /tools/generate_natvis
|
directory: /tools/generate_natvis
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
|
||||||
default-days: 7
|
|
||||||
|
|
||||||
- package-ecosystem: pip
|
- package-ecosystem: pip
|
||||||
directory: /tools/serve_header
|
directory: /tools/serve_header
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
|
||||||
default-days: 7
|
|
||||||
|
|
||||||
- package-ecosystem: pip
|
- package-ecosystem: pip
|
||||||
directory: /cmake/requirements
|
directory: /cmake/requirements
|
||||||
schedule:
|
schedule:
|
||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
|
||||||
default-days: 7
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
# SEMGREP_APP_TOKEN is still passed through so registry auth works if a
|
# SEMGREP_APP_TOKEN is still passed through so registry auth works if a
|
||||||
# token is ever added.
|
# token is ever added.
|
||||||
- name: Install Semgrep
|
- name: Install Semgrep
|
||||||
run: python3 -m pip install --user semgrep==1.168.0
|
run: python3 -m pip install --user semgrep
|
||||||
|
|
||||||
# `semgrep scan --sarif` always exits 0 even with findings; continue-on-error
|
# `semgrep scan --sarif` always exits 0 even with findings; continue-on-error
|
||||||
# is a safety net so the SARIF upload still runs if the scan itself errors.
|
# is a safety net so the SARIF upload still runs if the scan itself errors.
|
||||||
|
|||||||
@@ -234,22 +234,11 @@ jobs:
|
|||||||
|
|
||||||
ci_cuda_example:
|
ci_cuda_example:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
container: ghcr.io/nlohmann/json-ci:v2.4.0
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# 11.8.0: newest pre-C++20 CUDA release, exercises the C++17 fallback
|
|
||||||
# path (tests/cuda_example/CMakeLists.txt picks the standard per nvcc
|
|
||||||
# version); 12.1.1: permanent regression guard for #3907 (nvcc 12.0/12.1
|
|
||||||
# choke on enable_borrowed_range at C++20, fixed in 12.2); 12.6.3: recent
|
|
||||||
# CUDA/C++20 coverage.
|
|
||||||
cuda: ['11.8.0', '12.1.1', '12.6.3']
|
|
||||||
container: nvidia/cuda:${{ matrix.cuda }}-devel-ubuntu22.04
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Get latest CMake and ninja
|
|
||||||
uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4
|
|
||||||
- name: Run CMake
|
- name: Run CMake
|
||||||
run: cmake -S . -B build -DJSON_CI=On
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
@@ -90,13 +90,11 @@ jobs:
|
|||||||
- name: Get latest CMake and ninja
|
- name: Get latest CMake and ninja
|
||||||
uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4
|
uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4
|
||||||
- name: Set extra CXX_FLAGS for latest std_version
|
- name: Set extra CXX_FLAGS for latest std_version
|
||||||
# /wd5285 silences C5285 emitted by the bundled third-party doctest.h, which
|
|
||||||
# specializes std::tuple (newly diagnosed by the VS2026 v145 toolset)
|
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ matrix.std_version }}" = "latest" ]; then
|
if [ "${{ matrix.std_version }}" = "latest" ]; then
|
||||||
echo "flags=/permissive- /std:c++latest /utf-8 /W4 /WX /wd5285" >> $GITHUB_ENV
|
echo "flags=/permissive- /std:c++latest /utf-8 /W4 /WX" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
echo "flags=/W4 /WX /wd5285" >> $GITHUB_ENV
|
echo "flags=/W4 /WX" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: Run CMake (Release)
|
- name: Run CMake (Release)
|
||||||
|
|||||||
+2
-6
@@ -669,6 +669,7 @@ add_custom_target(ci_test_compiler_default
|
|||||||
add_custom_target(ci_cuda_example
|
add_custom_target(ci_cuda_example
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||||
|
-DCMAKE_CUDA_HOST_COMPILER=g++-8
|
||||||
-S${PROJECT_SOURCE_DIR}/tests/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example
|
-S${PROJECT_SOURCE_DIR}/tests/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example
|
||||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_cuda_example
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_cuda_example
|
||||||
)
|
)
|
||||||
@@ -719,11 +720,6 @@ add_custom_target(ci_icpx
|
|||||||
# to zero and does not honor NaN ordering; -Kieee restores strict IEEE 754 behavior
|
# to zero and does not honor NaN ordering; -Kieee restores strict IEEE 754 behavior
|
||||||
# (needed for the dtoa/grisu and NaN-comparison code paths).
|
# (needed for the dtoa/grisu and NaN-comparison code paths).
|
||||||
#
|
#
|
||||||
# -tp=px pins the target processor to the generic x86-64 baseline (SSE2-only) to avoid
|
|
||||||
# a nvc++ 25.5 / LLVM issue: when nvc++ auto-detects -tp from the runner's CPU (e.g. -tp znver4),
|
|
||||||
# certain attribute combinations trigger an llc instruction-selection crash on std::ldexp<unsigned>.
|
|
||||||
# Pinning to px removes this variability and is robust to future llc/nvc++ updates.
|
|
||||||
#
|
|
||||||
# The following tests are excluded as they trigger known nvc++ 25.5 defects (not
|
# The following tests are excluded as they trigger known nvc++ 25.5 defects (not
|
||||||
# library bugs); see https://github.com/nlohmann/json for tracking. Only the
|
# library bugs); see https://github.com/nlohmann/json for tracking. Only the
|
||||||
# affected language-standard variants are excluded so coverage is otherwise kept:
|
# affected language-standard variants are excluded so coverage is otherwise kept:
|
||||||
@@ -737,7 +733,7 @@ add_custom_target(ci_nvhpc
|
|||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||||
-DCMAKE_C_COMPILER=nvc -DCMAKE_CXX_COMPILER=nvc++
|
-DCMAKE_C_COMPILER=nvc -DCMAKE_CXX_COMPILER=nvc++
|
||||||
-DCMAKE_CXX_FLAGS="-Kieee;-tp=px"
|
-DCMAKE_CXX_FLAGS=-Kieee
|
||||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_nvhpc
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_nvhpc
|
||||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_nvhpc
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_nvhpc
|
||||||
|
|||||||
@@ -5,11 +5,8 @@
|
|||||||
# -Wno-extra-semi-stmt The library uses assert which triggers this warning.
|
# -Wno-extra-semi-stmt The library uses assert which triggers this warning.
|
||||||
# -Wno-padded We do not care about padding warnings.
|
# -Wno-padded We do not care about padding warnings.
|
||||||
# -Wno-covered-switch-default All switches list all cases and a default case.
|
# -Wno-covered-switch-default All switches list all cases and a default case.
|
||||||
# -Wno-unsafe-buffer-usage Pervasive: the library's own low-level numeric/buffer code
|
# -Wno-unsafe-buffer-usage Otherwise library code (strlen) would not compile.
|
||||||
# (to_chars, serializer, lexer, binary reader/writer, input
|
# -Wno-missing-noreturn We found no way to silence this warning otherwise, see PR #4871
|
||||||
# adapters, json_pointer) plus vendored Doctest itself (~208
|
|
||||||
# distinct sites measured 2026-07-08 on clang trunk) all use
|
|
||||||
# raw pointer arithmetic / libc string calls by necessity.
|
|
||||||
|
|
||||||
set(CLANG_CXXFLAGS
|
set(CLANG_CXXFLAGS
|
||||||
-Werror
|
-Werror
|
||||||
@@ -21,4 +18,5 @@ set(CLANG_CXXFLAGS
|
|||||||
-Wno-padded
|
-Wno-padded
|
||||||
-Wno-covered-switch-default
|
-Wno-covered-switch-default
|
||||||
-Wno-unsafe-buffer-usage
|
-Wno-unsafe-buffer-usage
|
||||||
|
-Wno-missing-noreturn
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
# -Wno-aggregate-return The library uses aggregate returns.
|
# -Wno-aggregate-return The library uses aggregate returns.
|
||||||
# -Wno-long-long The library uses the long long type to interface with system functions.
|
# -Wno-long-long The library uses the long long type to interface with system functions.
|
||||||
# -Wno-namespaces The library uses namespaces.
|
# -Wno-namespaces The library uses namespaces.
|
||||||
# -Wno-nrvo Doctest triggers this warning.
|
|
||||||
# -Wno-padded We do not care about padding warnings.
|
# -Wno-padded We do not care about padding warnings.
|
||||||
# -Wno-system-headers We do not care about warnings in system headers.
|
# -Wno-system-headers We do not care about warnings in system headers.
|
||||||
# -Wno-templates The library uses templates.
|
# -Wno-templates The library uses templates.
|
||||||
@@ -232,7 +231,6 @@ set(GCC_CXXFLAGS
|
|||||||
-Wnonnull
|
-Wnonnull
|
||||||
-Wnonnull-compare
|
-Wnonnull-compare
|
||||||
-Wnormalized=nfkc
|
-Wnormalized=nfkc
|
||||||
-Wno-nrvo
|
|
||||||
-Wnull-dereference
|
-Wnull-dereference
|
||||||
-Wodr
|
-Wodr
|
||||||
-Wold-style-cast
|
-Wold-style-cast
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"archive": "JSON_for_Modern_C++.tgz",
|
"archive": "JSON_for_Modern_C++.tgz",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Niels Lohmann",
|
"name": "Niels Lohmann",
|
||||||
"link": "https://nlohmann.me"
|
"link": "https://twitter.com/nlohmann"
|
||||||
},
|
},
|
||||||
"aliases": ["nlohmann/json"]
|
"aliases": ["nlohmann/json"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ A UTF-8 byte order mark is silently ignored.
|
|||||||
- Added in version 3.0.0.
|
- Added in version 3.0.0.
|
||||||
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
||||||
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
|
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
|
||||||
- Added `ignore_trailing_commas` in version 3.13.0.
|
- Added `ignore_trailing_commas` in version 3.12.x.
|
||||||
|
|
||||||
!!! warning "Deprecation"
|
!!! warning "Deprecation"
|
||||||
|
|
||||||
|
|||||||
@@ -82,13 +82,7 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
4. This is a constructor for existing `basic_json` types. It does not hijack copy/move constructors, since the parameter
|
4. This is a constructor for existing `basic_json` types. It does not hijack copy/move constructors, since the parameter
|
||||||
has different template arguments than the current ones.
|
has different template arguments than the current ones.
|
||||||
|
|
||||||
The constructor tries to convert the internal `m_value` of the parameter. Each member value (object, array, string,
|
The constructor tries to convert the internal `m_value` of the parameter.
|
||||||
etc.) is serialized via the corresponding `to_json()` overload. For objects and strings, the conversion requires
|
|
||||||
that the *target* `basic_json` type's `object_t::key_type` (or `string_t`) be directly constructible from the
|
|
||||||
*source* type's corresponding member type via `is_constructible`. If this requirement is not met, the conversion
|
|
||||||
does not fail to compile; instead, it silently falls back to the array-conversion path, which represents objects
|
|
||||||
as arrays of `[key, value]` pairs and strings as arrays of character codes. This is a known limitation tracked in
|
|
||||||
[issue #3425](https://github.com/nlohmann/json/issues/3425).
|
|
||||||
|
|
||||||
5. Creates a JSON value of type array or object from the passed initializer list `init`. In case `type_deduction` is
|
5. Creates a JSON value of type array or object from the passed initializer list `init`. In case `type_deduction` is
|
||||||
`#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init`
|
`#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init`
|
||||||
@@ -152,11 +146,6 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
|
|
||||||
- `BasicJsonType` is a `basic_json` type.
|
- `BasicJsonType` is a `basic_json` type.
|
||||||
- `BasicJsonType` has different template arguments than `basic_json_t`.
|
- `BasicJsonType` has different template arguments than `basic_json_t`.
|
||||||
|
|
||||||
**Note:** For cross-`basic_json` conversions to produce correct results, the target `basic_json`'s
|
|
||||||
`object_t::key_type` and `string_t` must be directly constructible from the source `basic_json`'s
|
|
||||||
corresponding types. See the description of overload (4) above for details on what happens when
|
|
||||||
this requirement is not met.
|
|
||||||
|
|
||||||
`U`:
|
`U`:
|
||||||
: `uncvref_t<CompatibleType>`
|
: `uncvref_t<CompatibleType>`
|
||||||
|
|||||||
@@ -92,4 +92,4 @@ std::string format_as(const BasicJsonType& j)
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
- Added in version 3.12.x.
|
||||||
|
|||||||
@@ -114,13 +114,6 @@ overload (3).
|
|||||||
See [Number conversion](../../features/types/number_handling.md#number-conversion)
|
See [Number conversion](../../features/types/number_handling.md#number-conversion)
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
!!! note "`std::optional` conversions"
|
|
||||||
|
|
||||||
Prior to version 3.13.0, `#!cpp get<std::optional<T>>()` (and other conversions to `std::optional<T>`) failed to
|
|
||||||
compile in every configuration, due to an internal implementation bug that made the `from_json` overload for
|
|
||||||
`std::optional` unreachable regardless of the [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md)
|
|
||||||
setting. This has been fixed.
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ behavior:
|
|||||||
object will agree on the name-value mappings.
|
object will agree on the name-value mappings.
|
||||||
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be
|
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be
|
||||||
chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or
|
chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or
|
||||||
`#!json {"key": 2}`. To reject duplicate keys instead of silently resolving them one way or another, see
|
`#!json {"key": 2}`.
|
||||||
[this parsing recipe](../../features/parsing/parser_callbacks.md#recipe-rejecting-duplicate-object-keys).
|
|
||||||
- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see
|
- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see
|
||||||
[`dump`](dump.md)) in this order. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored
|
[`dump`](dump.md)) in this order. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored
|
||||||
and serialized as `#!json {"a": 2, "b": 1}`.
|
and serialized as `#!json {"a": 2, "b": 1}`.
|
||||||
@@ -94,15 +93,6 @@ alphabetical order as `std::map` with `std::less` is used by default. Please not
|
|||||||
[RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON
|
[RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
#### Cross-`basic_json` conversion requirements
|
|
||||||
|
|
||||||
When converting an object from one `basic_json` specialization to another via the
|
|
||||||
[converting constructor](basic_json.md#overload-4), the target `object_t`'s `key_type` must be
|
|
||||||
directly constructible from the source `basic_json`'s `string_t` type (or more generally, from the
|
|
||||||
source object's key type). If this requirement is not met, the conversion does not fail; instead,
|
|
||||||
the object is silently converted as an array of key-value pairs, which is incorrect. See
|
|
||||||
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|||||||
@@ -251,6 +251,5 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
|||||||
1. Added in version 1.0.0.
|
1. Added in version 1.0.0.
|
||||||
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3)
|
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3)
|
||||||
in version 3.11.0.
|
in version 3.11.0.
|
||||||
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
|
3. Added in version 3.11.0.
|
||||||
already supported by [`at`](at.md), [`value`](value.md), [`find`](find.md), and other lookup functions.
|
|
||||||
4. Added in version 2.0.0.
|
4. Added in version 2.0.0.
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ class basic_json {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Compares two JSON values for inequality. Returns `#!cpp !(lhs == rhs)` (until C++20) or `#!cpp !(*this == rhs)` (since C++20).
|
1. Compares two JSON values for inequality according to the following rules:
|
||||||
- This means the comparison is simply the logical negation of `operator==`, including for special values like `NaN` and `discarded`.
|
- The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either operand is `NaN` and
|
||||||
|
the other operand is either `NaN` or any other number.
|
||||||
|
- Otherwise, returns the result of `#!cpp !(lhs == rhs)` (until C++20) or `#!cpp !(*this == rhs)` (since C++20).
|
||||||
|
|
||||||
2. Compares a JSON value and a scalar or a scalar and a JSON value for inequality by converting the scalar to a JSON
|
2. Compares a JSON value and a scalar or a scalar and a JSON value for inequality by converting the scalar to a JSON
|
||||||
value and comparing both JSON values according to 1.
|
value and comparing both JSON values according to 1.
|
||||||
@@ -52,12 +54,13 @@ Linear.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
!!! note "Comparing `NaN` and `discarded`"
|
!!! note "Comparing `NaN`"
|
||||||
|
|
||||||
Since `operator!=` is defined as `!(a == b)`, the behavior for special values follows that of `operator==`:
|
`NaN` values are unordered within the domain of numbers.
|
||||||
|
The following comparisons all yield `#!cpp false`:
|
||||||
- For `NaN` values: `NaN == NaN` yields `#!cpp false`, so `NaN != NaN` yields `#!cpp true`.
|
1. Comparing a `NaN` with itself.
|
||||||
- For `discarded` values: `discarded == x` yields `#!cpp false` for any `x`, so `discarded != x` yields `#!cpp true`.
|
2. Comparing a `NaN` with another `NaN`.
|
||||||
|
3. Comparing a `NaN` and any other number.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@@ -91,7 +94,5 @@ Linear.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. Changed in version 3.13.0 to remove
|
1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
||||||
special-casing for `NaN` and `discarded` values; `operator!=` now consistently means `!(a == b)`.
|
2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
||||||
2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. Changed in version 3.13.0 to remove
|
|
||||||
special-casing for `NaN` and `discarded` values; `operator!=` now consistently means `!(a == b)`.
|
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ Invalid Unicode escapes and unpaired surrogates in the input are reported as
|
|||||||
- Overload for contiguous containers (1) added in version 2.0.3.
|
- Overload for contiguous containers (1) added in version 2.0.3.
|
||||||
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
||||||
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
|
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
|
||||||
- Added `ignore_trailing_commas` in version 3.13.0.
|
- Added `ignore_trailing_commas` in version 3.12.x.
|
||||||
|
|
||||||
!!! warning "Deprecation"
|
!!! warning "Deprecation"
|
||||||
|
|
||||||
|
|||||||
@@ -74,4 +74,4 @@ is thrown. In any case, the original value is not changed: the patch is applied
|
|||||||
|
|
||||||
- Added in version 2.0.0.
|
- Added in version 2.0.0.
|
||||||
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
||||||
target location has a non-object/non-array parent in version 3.13.0.
|
target location has a non-object/non-array parent in version 3.12.x.
|
||||||
|
|||||||
@@ -71,4 +71,4 @@ function throws an exception.
|
|||||||
|
|
||||||
- Added in version 3.11.0.
|
- Added in version 3.11.0.
|
||||||
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
||||||
target location has a non-object/non-array parent in version 3.13.0.
|
target location has a non-object/non-array parent in version 3.12.x.
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ A UTF-8 byte order mark is silently ignored.
|
|||||||
|
|
||||||
- Added in version 3.2.0.
|
- Added in version 3.2.0.
|
||||||
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
||||||
- Added `ignore_trailing_commas` in version 3.13.0.
|
- Added `ignore_trailing_commas` in version 3.12.x.
|
||||||
|
|
||||||
!!! warning "Deprecation"
|
!!! warning "Deprecation"
|
||||||
|
|
||||||
|
|||||||
@@ -54,4 +54,4 @@ provides `<format>`, controlled by the [`JSON_HAS_STD_FORMAT`](../macros/json_ha
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
- Added in version 3.12.x.
|
||||||
|
|||||||
@@ -45,15 +45,6 @@ This implementation is interoperable as it does compare strings code unit by cod
|
|||||||
String values are stored as pointers in a `basic_json` type. That is, for any access to string values, a pointer of type
|
String values are stored as pointers in a `basic_json` type. That is, for any access to string values, a pointer of type
|
||||||
`string_t*` must be dereferenced.
|
`string_t*` must be dereferenced.
|
||||||
|
|
||||||
#### Cross-`basic_json` conversion requirements
|
|
||||||
|
|
||||||
When converting a string value from one `basic_json` specialization to another via the
|
|
||||||
[converting constructor](basic_json.md#overload-4), the target `string_t` must be directly
|
|
||||||
constructible from the source `basic_json`'s `string_t` type. If this requirement is not met, the
|
|
||||||
conversion does not fail; instead, the string is silently converted as an array of character codes,
|
|
||||||
which is incorrect. See [issue #3425](https://github.com/nlohmann/json/issues/3425) for details
|
|
||||||
and an example.
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|||||||
@@ -21,12 +21,6 @@ a string representation of the type ([`value_t`](value_t.md)):
|
|||||||
| array | `"array"` |
|
| array | `"array"` |
|
||||||
| binary | `"binary"` |
|
| binary | `"binary"` |
|
||||||
| discarded | `"discarded"` |
|
| discarded | `"discarded"` |
|
||||||
| invalid (corrupted value) | `"invalid"` |
|
|
||||||
|
|
||||||
!!! note "The \"invalid\" type"
|
|
||||||
|
|
||||||
The `"invalid"` return value indicates a corrupted JSON value — this can occur if an enum value falls outside the
|
|
||||||
range of valid `value_t` values. This is useful for diagnosing data corruption or internal errors.
|
|
||||||
|
|
||||||
## Exception safety
|
## Exception safety
|
||||||
|
|
||||||
@@ -58,4 +52,3 @@ Constant.
|
|||||||
- Part of the public API version since 2.1.0.
|
- Part of the public API version since 2.1.0.
|
||||||
- Changed return value to `const char*` and added `noexcept` in version 3.0.0.
|
- Changed return value to `const char*` and added `noexcept` in version 3.0.0.
|
||||||
- Added support for binary type in version 3.8.0.
|
- Added support for binary type in version 3.8.0.
|
||||||
- Added `"invalid"` return value for corrupted JSON values in version 3.13.0.
|
|
||||||
|
|||||||
@@ -184,6 +184,4 @@ changes to any JSON value.
|
|||||||
|
|
||||||
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0.
|
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0.
|
||||||
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2.
|
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2.
|
||||||
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0, including fixing an issue where resolving
|
3. Added in version 2.0.2. Extended to work with arrays in version 3.12.x.
|
||||||
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
|
|
||||||
`default_value`, as documented).
|
|
||||||
|
|||||||
@@ -36,4 +36,4 @@ Constant.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
- Added in version 3.12.x.
|
||||||
|
|||||||
@@ -32,4 +32,4 @@ Linear in the number of reference tokens in the `json_pointer`.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
- Added in version 3.12.x.
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ Linear in the number of reference tokens in the `json_pointer`.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
- Added in version 3.12.x.
|
||||||
|
|||||||
@@ -92,4 +92,4 @@ The default value is `0` (disabled — existing behavior is preserved).
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
- Added in version 3.12.x.
|
||||||
|
|||||||
@@ -44,4 +44,4 @@ The default value is detected based on preprocessor macros such as `#!cpp __cplu
|
|||||||
|
|
||||||
- Added in version 3.10.5.
|
- Added in version 3.10.5.
|
||||||
- Added `JSON_HAS_CPP_23` in version 3.12.0.
|
- Added `JSON_HAS_CPP_23` in version 3.12.0.
|
||||||
- Added `JSON_HAS_CPP_26` in version 3.13.0.
|
- Added `JSON_HAS_CPP_26` in version 3.12.x.
|
||||||
|
|||||||
@@ -19,20 +19,6 @@ The default value is detected based on the preprocessor macros `#!cpp __cpp_lib_
|
|||||||
`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include(<filesystem>)`, or
|
`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include(<filesystem>)`, or
|
||||||
`#!cpp __has_include(<experimental/filesystem>)`.
|
`#!cpp __has_include(<experimental/filesystem>)`.
|
||||||
|
|
||||||
!!! info "Known compiler/stdlib exclusions"
|
|
||||||
|
|
||||||
Even when the feature-test macro indicates filesystem support is available, the library disables it on the following broken toolchains:
|
|
||||||
|
|
||||||
- **MinGW + GCC 8** — disabled entirely (broken `std::filesystem` implementation; [MinGW-w64 bug 737](https://sourceforge.net/p/mingw-w64/bugs/737/))
|
|
||||||
- **GCC (non-Clang) < 8** — disabled (no filesystem support)
|
|
||||||
- **Clang < 7** — disabled (no filesystem support)
|
|
||||||
- **MSVC < 19.14** — disabled (no filesystem support)
|
|
||||||
- **iOS < 13** — disabled (no filesystem support)
|
|
||||||
- **macOS < Catalina (10.15)** — disabled (no filesystem support)
|
|
||||||
|
|
||||||
If `JSON_HAS_FILESYSTEM` or `JSON_HAS_EXPERIMENTAL_FILESYSTEM` is `0` despite `__cpp_lib_filesystem` being defined, one
|
|
||||||
of the exclusions above likely applies to your toolchain.
|
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- Note that older compilers or older versions of libstdc++ also require the library `stdc++fs` to be linked to for
|
- Note that older compilers or older versions of libstdc++ also require the library `stdc++fs` to be linked to for
|
||||||
|
|||||||
@@ -13,20 +13,6 @@ The default value is detected based on the preprocessor macro `#!cpp __cpp_lib_r
|
|||||||
|
|
||||||
When the macro is not defined, the library will define it to its default value.
|
When the macro is not defined, the library will define it to its default value.
|
||||||
|
|
||||||
!!! info "Known compiler/stdlib exclusions"
|
|
||||||
|
|
||||||
Even when the feature-test macro `__cpp_lib_ranges` indicates ranges support is available, the library disables it on
|
|
||||||
the following incomplete or broken toolchains:
|
|
||||||
|
|
||||||
- **GCC 11.1.0** — disabled (the shipped `<ranges>` header has a syntax error; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
|
||||||
- **libstdc++ < 11** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
|
||||||
- **Clang < 16 with libstdc++** — disabled (incomplete ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
|
||||||
- **libc++ < 160000** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
|
||||||
- **nvcc (CUDA) 12.0.x and 12.1.x** — disabled (the `enable_borrowed_range` variable-template syntax triggers a parse error
|
|
||||||
under these two toolkit versions; fixed in CUDA 12.2; [issue #3907](https://github.com/nlohmann/json/issues/3907))
|
|
||||||
|
|
||||||
If `JSON_HAS_RANGES` is `0` despite `__cpp_lib_ranges` being defined, one of the exclusions above likely applies to your toolchain.
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|||||||
@@ -38,4 +38,4 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
- Added in version 3.12.x.
|
||||||
|
|||||||
@@ -75,4 +75,4 @@ For further information please refer to the corresponding macros without `WITH_N
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
1. Added in version 3.13.0.
|
1. Added in version 3.12.x.
|
||||||
|
|||||||
@@ -102,4 +102,4 @@ inline void from_json(const BasicJsonType& j, type& e);
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
Added in version 3.13.0.
|
Added in version 3.12.x.
|
||||||
|
|||||||
@@ -64,4 +64,4 @@ Linear.
|
|||||||
|
|
||||||
- Added in version 1.0.0.
|
- Added in version 1.0.0.
|
||||||
- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0.
|
- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0.
|
||||||
- Added `char8_t*` overload in 3.13.0.
|
- Added `char8_t*` overload in 3.12.x.
|
||||||
|
|||||||
@@ -63,4 +63,4 @@ Linear.
|
|||||||
|
|
||||||
- Added in version 2.0.0.
|
- Added in version 2.0.0.
|
||||||
- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0.
|
- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0.
|
||||||
- Added `char8_t*` overload in 3.13.0.
|
- Added `char8_t*` overload in 3.12.x.
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ violations will result in a failed build.
|
|||||||
|
|
||||||
Any compiler with complete C++11 support can compile the library without warnings.
|
Any compiler with complete C++11 support can compile the library without warnings.
|
||||||
|
|
||||||
Note: C++20 modules support may hit compiler-specific issues not covered by the general compiler matrix below. See [Modules](../features/modules.md#known-issues) for known issues and workarounds.
|
|
||||||
|
|
||||||
Note: Some modern features (like C++20 ranges or filesystem support) may be disabled on specific broken or incomplete toolchains even when standard feature-test macros indicate support. See [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md) and [`JSON_HAS_FILESYSTEM`](../api/macros/json_has_filesystem.md) for details on known exclusions.
|
|
||||||
|
|
||||||
- [x] The library is compiled with 50+ different C++ compilers with different operating systems and platforms,
|
- [x] The library is compiled with 50+ different C++ compilers with different operating systems and platforms,
|
||||||
including the oldest versions known to compile the library.
|
including the oldest versions known to compile the library.
|
||||||
|
|
||||||
@@ -66,9 +62,7 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
|||||||
| Clang 20.1.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| Clang 20.1.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| Clang 20.1.8 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub |
|
| Clang 20.1.8 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub |
|
||||||
| Clang 21.1.8 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| Clang 21.1.8 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| CUDA 11.8.0 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
| CUDA 11.0.221 (nvcc) | x86_64 | Ubuntu 20.04 LTS | GitHub |
|
||||||
| CUDA 12.1.1 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
|
||||||
| CUDA 12.6.3 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
|
||||||
| Emscripten 4.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| Emscripten 4.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 4.8.5 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 4.8.5 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 4.9.3 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 4.9.3 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
json parse_strict(const std::string& input)
|
|
||||||
{
|
|
||||||
// one key set per nesting depth, reused across sibling objects
|
|
||||||
std::vector<std::unordered_set<std::string>> keys;
|
|
||||||
|
|
||||||
auto reject_duplicate_keys = [&](int depth, json::parse_event_t event, json & parsed)
|
|
||||||
{
|
|
||||||
if (event == json::parse_event_t::object_start)
|
|
||||||
{
|
|
||||||
// keys of this object are reported at depth+1 (see the event table above)
|
|
||||||
const auto child_depth = static_cast<std::size_t>(depth) + 1;
|
|
||||||
if (keys.size() <= child_depth)
|
|
||||||
{
|
|
||||||
keys.resize(child_depth + 1);
|
|
||||||
}
|
|
||||||
keys[child_depth].clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == json::parse_event_t::key)
|
|
||||||
{
|
|
||||||
auto& seen = keys[static_cast<std::size_t>(depth)];
|
|
||||||
const auto& key = parsed.get_ref<const std::string&>();
|
|
||||||
if (!seen.insert(key).second)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("duplicate JSON object key: " + key);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
return json::parse(input, reject_duplicate_keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// parsing succeeds when all keys are unique
|
|
||||||
json j = parse_strict(R"({"one": 1, "two": 2})");
|
|
||||||
std::cout << j << '\n';
|
|
||||||
|
|
||||||
// parsing throws when a key is repeated
|
|
||||||
try
|
|
||||||
{
|
|
||||||
parse_strict(R"({"one": 1, "one": 2})");
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cout << e.what() << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
{"one":1,"two":2}
|
|
||||||
duplicate JSON object key: one
|
|
||||||
@@ -66,15 +66,7 @@ see "binary" cells in the table above.
|
|||||||
|
|
||||||
!!! info "NaN/infinity handling"
|
!!! info "NaN/infinity handling"
|
||||||
|
|
||||||
`NaN`, `Infinity`, and `-Infinity` are serialized as a CBOR half-precision float (type 0xF9, 3 bytes total):
|
If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the normal JSON serialization which serializes NaN or Infinity to `null`.
|
||||||
`NaN` as `0xF9 0x7E 0x00`, `Infinity` as `0xF9 0x7C 0x00`, and `-Infinity` as `0xF9 0xFC 0x00`. This behavior
|
|
||||||
differs from the normal JSON serialization which serializes NaN or Infinity to `null`.
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
|
|
||||||
Prior to version 3.13.0, NaN and Infinity were instead serialized as a CBOR double-precision float (type 0xFB,
|
|
||||||
9 bytes total), because the check used to select a smaller encoding compared magnitudes with NaN, which is
|
|
||||||
always `false` and caused the intended half-precision path to be skipped.
|
|
||||||
|
|
||||||
!!! info "Unused CBOR types"
|
!!! info "Unused CBOR types"
|
||||||
|
|
||||||
@@ -168,13 +160,6 @@ The library maps CBOR types to JSON value types as follows:
|
|||||||
- simple values (0xE0..0xF3, 0xF8)
|
- simple values (0xE0..0xF3, 0xF8)
|
||||||
- undefined (0xF7)
|
- undefined (0xF7)
|
||||||
|
|
||||||
!!! warning "Negative integer overflow"
|
|
||||||
|
|
||||||
CBOR negative integers (major type 1) are decoded as `-1 - n`. If the encoded magnitude `n` is too large for the
|
|
||||||
result to fit into `number_integer_t` (`std::int64_t` by default), parsing fails with a
|
|
||||||
[`parse_error.112`](../../home/exceptions.md#jsonexceptionparse_error112) exception rather than overflowing
|
|
||||||
silently.
|
|
||||||
|
|
||||||
!!! warning "Object keys"
|
!!! warning "Object keys"
|
||||||
|
|
||||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
||||||
|
|||||||
@@ -67,15 +67,8 @@ specification:
|
|||||||
|
|
||||||
!!! info "NaN/infinity handling"
|
!!! info "NaN/infinity handling"
|
||||||
|
|
||||||
`NaN`, `Infinity`, and `-Infinity` are serialized as a MessagePack float 32 (type 0xCA, 5 bytes total),
|
If NaN or Infinity are stored inside a JSON number, they are serialized properly in contrast to the
|
||||||
regardless of magnitude, in contrast to the [dump](../../api/basic_json/dump.md) function which serializes NaN
|
[dump](../../api/basic_json/dump.md) function which serializes NaN or Infinity to `null`.
|
||||||
or Infinity to `null`.
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
|
|
||||||
Prior to version 3.13.0, NaN and Infinity were instead serialized as a MessagePack float 64 (type 0xCB, 9 bytes
|
|
||||||
total), because the check used to select the smaller float 32 encoding compared magnitudes with NaN, which is
|
|
||||||
always `false` and caused the float 32 path to be skipped.
|
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|
||||||
|
|||||||
@@ -66,24 +66,6 @@ which forces the explicit `get` form and can catch unintended conversions at com
|
|||||||
floating-point value as an integer truncates it, and narrowing conversions may overflow. See
|
floating-point value as an integer truncates it, and narrowing conversions may overflow. See
|
||||||
[number conversion](types/number_handling.md#number-conversion) for details and how to guard against it.
|
[number conversion](types/number_handling.md#number-conversion) for details and how to guard against it.
|
||||||
|
|
||||||
!!! warning "std::optional direct construction from JSON null throws"
|
|
||||||
|
|
||||||
Constructing or assigning `std::optional<T>` directly from a JSON value does not correctly produce
|
|
||||||
`std::nullopt` for a JSON `null`:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
json j_null;
|
|
||||||
std::optional<std::string> opt = j_null; // ❌ throws type_error 302
|
|
||||||
```
|
|
||||||
|
|
||||||
This is due to C++ language rules: `std::optional<T>` has its own converting constructor that is chosen over
|
|
||||||
`basic_json::operator T()` when both are viable. Use `get<std::optional<T>>()` or `get_to()` instead:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
auto opt = j_null.get<std::optional<std::string>>(); // ✅ std::nullopt
|
|
||||||
j_null.get_to(opt); // ✅ std::nullopt
|
|
||||||
```
|
|
||||||
|
|
||||||
## Putting values in
|
## Putting values in
|
||||||
|
|
||||||
The reverse direction works the same way: assigning or constructing a `json` from a C++ value converts it to JSON.
|
The reverse direction works the same way: assigning or constructing a `json` from a C++ value converts it to JSON.
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ json data = json::parse(f);
|
|||||||
It should be noted that as modules do not export macros, the `nlohmann.json` module will not export any macros.
|
It should be noted that as modules do not export macros, the `nlohmann.json` module will not export any macros.
|
||||||
|
|
||||||
## Exported symbols
|
## Exported symbols
|
||||||
|
|
||||||
Only the following symbols are exported from `nlohmann.json`:
|
Only the following symbols are exported from `nlohmann.json`:
|
||||||
|
|
||||||
- `nlohmann::adl_serializer`
|
- `nlohmann::adl_serializer`
|
||||||
@@ -39,21 +38,3 @@ Only the following symbols are exported from `nlohmann.json`:
|
|||||||
- `nlohmann::to_string`
|
- `nlohmann::to_string`
|
||||||
- `nlohmann::literals::json_literals::operator""_json`
|
- `nlohmann::literals::json_literals::operator""_json`
|
||||||
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
||||||
|
|
||||||
Additionally, the following `nlohmann::detail` symbols are exported, solely to work around an MSVC compilation issue
|
|
||||||
([#3970](https://github.com/nlohmann/json/issues/3970)). They are implementation details, not part of the public API,
|
|
||||||
and should not be used directly:
|
|
||||||
|
|
||||||
- `nlohmann::detail::json_sax_dom_callback_parser`
|
|
||||||
- `nlohmann::detail::unknown_size`
|
|
||||||
|
|
||||||
## Known issues
|
|
||||||
|
|
||||||
C++20 modules support is exercised in CI against current GCC and Clang on Ubuntu, and the default MSVC toolset on Windows Server 2022 — there is no documented minimum compiler version, unlike feature-test-macro-gated features such as [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md).
|
|
||||||
|
|
||||||
!!! info "Known compiler issues"
|
|
||||||
|
|
||||||
- **GCC** may emit "redefinition" errors when `#include <nlohmann/json.hpp>` appears in a module preamble together with other imports. This is an upstream GCC bug, not yet resolved as of GCC 16. Workarounds: include `nlohmann/json.hpp` before other `#include`s, use `import nlohmann.json;` instead, or upgrade GCC. ([issue #5103](https://github.com/nlohmann/json/issues/5103))
|
|
||||||
- **MSVC** could fail with `C2039: 'json_sax_dom_callback_parser' is not a member of ... detail`; fixed by exporting the required internal symbols from `json.cppm` (see [Exported symbols](#exported-symbols) above). ([issue #3970](https://github.com/nlohmann/json/issues/3970))
|
|
||||||
|
|
||||||
If you hit a different module-related build failure, search [existing issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+modules) before filing a new one.
|
|
||||||
|
|||||||
@@ -81,34 +81,3 @@ was called:
|
|||||||
```json
|
```json
|
||||||
--8<-- "examples/parse__string__parser_callback_t.output"
|
--8<-- "examples/parse__string__parser_callback_t.output"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Recipe: rejecting duplicate object keys
|
|
||||||
|
|
||||||
The JSON specification leaves the handling of objects with repeated keys up to the implementation. As described in
|
|
||||||
[`object_t`](../../api/basic_json/object_t.md#behavior), it is unspecified which value for a repeated key ends up in
|
|
||||||
the resulting `#!c json` value -- once parsing has produced that value, the duplicate is already gone, because object
|
|
||||||
storage maps each key to a single value. If duplicate keys should instead be treated as an error, a parser callback
|
|
||||||
can detect them while the object is still being read, before that ambiguity ever applies.
|
|
||||||
|
|
||||||
??? example
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
--8<-- "examples/reject_duplicate_keys.cpp"
|
|
||||||
```
|
|
||||||
|
|
||||||
Output:
|
|
||||||
|
|
||||||
```json
|
|
||||||
--8<-- "examples/reject_duplicate_keys.output"
|
|
||||||
```
|
|
||||||
|
|
||||||
This approach has two limitations:
|
|
||||||
|
|
||||||
- The depth-indexed bookkeeping must account for the fact that `object_start` reports the depth of the *parent* of
|
|
||||||
the object, while the `key` events inside that object are reported one depth deeper (see the event table above);
|
|
||||||
it is easy to get this off by one for nested objects.
|
|
||||||
- The thrown exception cannot carry a `parse_error`-style byte offset, because position tracking only exists inside
|
|
||||||
the parser and lexer, not at the callback layer.
|
|
||||||
|
|
||||||
For strict validation with precise error positions, implementing a [SAX interface](sax_interface.md) instead gives
|
|
||||||
access to the parser's position information directly.
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ std::map<
|
|||||||
The choice of `object_t` influences the behavior of the JSON class. With the default type, objects have the following behavior:
|
The choice of `object_t` influences the behavior of the JSON class. With the default type, objects have the following behavior:
|
||||||
|
|
||||||
- When all names are unique, objects will be interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings.
|
- When all names are unique, objects will be interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings.
|
||||||
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or `#!json {"key": 2}`. To reject duplicate keys instead of silently resolving them one way or another, see [this parsing recipe](../parsing/parser_callbacks.md#recipe-rejecting-duplicate-object-keys).
|
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or `#!json {"key": 2}`.
|
||||||
- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see `dump`) in this order. For instance, both `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored and serialized as `#!json {"a": 2, "b": 1}`.
|
- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see `dump`) in this order. For instance, both `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored and serialized as `#!json {"a": 2, "b": 1}`.
|
||||||
- When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be treated as equal.
|
- When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be treated as equal.
|
||||||
|
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ In the default [`json`](../../api/json.md) type, numbers are stored as `#!c std:
|
|||||||
number without loss of precision. If this is impossible (e.g., if the number is too large), the number is stored as
|
number without loss of precision. If this is impossible (e.g., if the number is too large), the number is stored as
|
||||||
`#!c double`.
|
`#!c double`.
|
||||||
|
|
||||||
Positive integers are stored as `#!c std::uint64_t`, while negative integers are stored as `#!c std::int64_t`. This
|
|
||||||
distinction is determined at parse time: if the JSON number has a leading minus sign, it uses signed integer storage;
|
|
||||||
otherwise, it uses unsigned integer storage.
|
|
||||||
|
|
||||||
!!! info "Notes"
|
!!! info "Notes"
|
||||||
|
|
||||||
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
|
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
|
||||||
|
|||||||
@@ -326,9 +326,6 @@ An unexpected byte was read in a [binary format](../features/binary_formats/inde
|
|||||||
```
|
```
|
||||||
[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1
|
[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1
|
||||||
```
|
```
|
||||||
```
|
|
||||||
[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow
|
|
||||||
```
|
|
||||||
|
|
||||||
### json.exception.parse_error.113
|
### json.exception.parse_error.113
|
||||||
|
|
||||||
@@ -896,7 +893,7 @@ A JSON Patch `add` operation cannot be applied because the target location's par
|
|||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
|
|
||||||
This exception was added in version 3.13.0. Before that, this situation hit an internal assertion (aborting the program in debug builds) or was silently ignored when assertions were disabled.
|
This exception was added in version 3.12.x. Before that, this situation hit an internal assertion (aborting the program in debug builds) or was silently ignored when assertions were disabled.
|
||||||
|
|
||||||
## Further exceptions
|
## Further exceptions
|
||||||
|
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ See [this section](../features/types/number_handling.md#number-serialization) on
|
|||||||
- Can I use `std::format("{}", j)` on a JSON value?
|
- Can I use `std::format("{}", j)` on a JSON value?
|
||||||
- Can I use `fmt::format("{}", j)` or `fmt::print("{}", j)` (the [{fmt}](https://github.com/fmtlib/fmt) library) on a JSON value?
|
- Can I use `fmt::format("{}", j)` or `fmt::print("{}", j)` (the [{fmt}](https://github.com/fmtlib/fmt) library) on a JSON value?
|
||||||
|
|
||||||
`std::format` works out of the box since version 3.13.0, as long as the standard library provides
|
`std::format` works out of the box since version 3.12.x, as long as the standard library provides
|
||||||
`<format>` (see [`JSON_HAS_STD_FORMAT`](../api/macros/json_has_std_format.md)); see
|
`<format>` (see [`JSON_HAS_STD_FORMAT`](../api/macros/json_has_std_format.md)); see
|
||||||
[`std::formatter<basic_json>`](../api/basic_json/std_formatter.md) for details, including the `#!cpp "{:#}"`
|
[`std::formatter<basic_json>`](../api/basic_json/std_formatter.md) for details, including the `#!cpp "{:#}"`
|
||||||
pretty-print spec, indent widths (`#!cpp "{:2}"`), and custom indent characters (`#!cpp "{:.>#}"`).
|
pretty-print spec, indent widths (`#!cpp "{:2}"`), and custom indent characters (`#!cpp "{:.>#}"`).
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
User-agent: *
|
|
||||||
Allow: /
|
|
||||||
|
|
||||||
Sitemap: https://json.nlohmann.me/sitemap.xml
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
"""Copy each documentation page's Markdown source into the built site."""
|
|
||||||
|
|
||||||
# Creates a `<path>.md` sibling of each HTML output (for example,
|
|
||||||
# `features/comments/` becomes `features/comments.md`) so agents and tools can
|
|
||||||
# fetch the raw Markdown directly instead of parsing rendered HTML.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
_pages = []
|
|
||||||
|
|
||||||
|
|
||||||
def on_files(files, config):
|
|
||||||
global _pages
|
|
||||||
_pages = [f for f in files if f.is_documentation_page()]
|
|
||||||
return files
|
|
||||||
|
|
||||||
|
|
||||||
def on_post_build(config):
|
|
||||||
site_dir = config["site_dir"]
|
|
||||||
for file in _pages:
|
|
||||||
url = file.url.rstrip("/")
|
|
||||||
target = os.path.join(site_dir, (url or "index") + ".md")
|
|
||||||
os.makedirs(os.path.dirname(target), exist_ok=True)
|
|
||||||
shutil.copyfile(file.abs_src_path, target)
|
|
||||||
@@ -367,9 +367,6 @@ markdown_extensions:
|
|||||||
auto_append:
|
auto_append:
|
||||||
- ../includes/glossary.md
|
- ../includes/glossary.md
|
||||||
|
|
||||||
hooks:
|
|
||||||
- hooks/copy_markdown_source.py
|
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- search:
|
- search:
|
||||||
separator: '[\s\-\.]'
|
separator: '[\s\-\.]'
|
||||||
@@ -392,33 +389,6 @@ plugins:
|
|||||||
- https://nlohmann.github.io/json/*
|
- https://nlohmann.github.io/json/*
|
||||||
- mailto:*
|
- mailto:*
|
||||||
- privacy
|
- privacy
|
||||||
- llmstxt:
|
|
||||||
markdown_description: >
|
|
||||||
JSON for Modern C++ is a C++11 header-only library implementing a JSON
|
|
||||||
value type with an STL-like API, JSON Pointer/Patch, CBOR/MessagePack/
|
|
||||||
BSON/UBJSON/BJData binary format support, and a SAX-style parser interface.
|
|
||||||
sections:
|
|
||||||
Home:
|
|
||||||
- index.md
|
|
||||||
- home/*.md
|
|
||||||
Features:
|
|
||||||
- features/*.md
|
|
||||||
- features/binary_formats/*.md
|
|
||||||
- features/element_access/*.md
|
|
||||||
- features/parsing/*.md
|
|
||||||
- features/types/*.md
|
|
||||||
Integration:
|
|
||||||
- integration/*.md
|
|
||||||
API Documentation:
|
|
||||||
- api/*.md
|
|
||||||
- api/basic_json/*.md
|
|
||||||
- api/adl_serializer/*.md
|
|
||||||
- api/byte_container_with_subtype/*.md
|
|
||||||
- api/json_pointer/*.md
|
|
||||||
- api/json_sax/*.md
|
|
||||||
- api/macros/*.md
|
|
||||||
Community:
|
|
||||||
- community/*.md
|
|
||||||
|
|
||||||
extra_css:
|
extra_css:
|
||||||
- css/custom.css
|
- css/custom.css
|
||||||
|
|||||||
@@ -7,6 +7,5 @@ mkdocs-material-extensions==1.3.1 # extensions
|
|||||||
mkdocs-minify-plugin==0.8.0 # plugin "minify"
|
mkdocs-minify-plugin==0.8.0 # plugin "minify"
|
||||||
mkdocs-redirects==1.2.3 # plugin "redirects"
|
mkdocs-redirects==1.2.3 # plugin "redirects"
|
||||||
mkdocs-htmlproofer-plugin==1.5.0 # plugin "htmlproofer"
|
mkdocs-htmlproofer-plugin==1.5.0 # plugin "htmlproofer"
|
||||||
mkdocs-llmstxt==0.5.0 # plugin "llmstxt"
|
|
||||||
|
|
||||||
PyYAML==6.0.3 # linter
|
PyYAML==6.0.3 # linter
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ class wide_string_input_adapter
|
|||||||
|
|
||||||
// parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
|
// parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
|
||||||
template<class T>
|
template<class T>
|
||||||
JSON_HEDLEY_NO_RETURN std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,11 +146,6 @@
|
|||||||
#define JSON_HAS_RANGES 0
|
#define JSON_HAS_RANGES 0
|
||||||
#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
|
#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
|
||||||
#define JSON_HAS_RANGES 0
|
#define JSON_HAS_RANGES 0
|
||||||
// nvcc CUDA 12.0/12.1 chokes on the enable_borrowed_range variable-template
|
|
||||||
// syntax when compiling as CUDA source; fixed in CUDA 12.2 (issue #3907)
|
|
||||||
#elif defined(__CUDACC__) && defined(__CUDACC_VER_MAJOR__) && __CUDACC_VER_MAJOR__ == 12 \
|
|
||||||
&& defined(__CUDACC_VER_MINOR__) && (__CUDACC_VER_MINOR__ == 0 || __CUDACC_VER_MINOR__ == 1)
|
|
||||||
#define JSON_HAS_RANGES 0
|
|
||||||
#elif defined(__cpp_lib_ranges)
|
#elif defined(__cpp_lib_ranges)
|
||||||
#define JSON_HAS_RANGES 1
|
#define JSON_HAS_RANGES 1
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -465,12 +465,18 @@ class serializer
|
|||||||
{
|
{
|
||||||
if (codepoint <= 0xFFFF)
|
if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(codepoint));
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
|
||||||
|
static_cast<std::uint16_t>(codepoint)));
|
||||||
|
bytes += 6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)));
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
|
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
|
||||||
|
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
|
||||||
|
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
|
||||||
|
bytes += 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -677,32 +683,6 @@ class serializer
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* @brief write a lowercase "\uXXXX" escape sequence into @a string_buffer
|
|
||||||
*
|
|
||||||
* Branch-free replacement for `snprintf(buf, 7, "\\u%04x", codeunit)` in the
|
|
||||||
* string escaping hot path. It writes exactly six characters ('\\', 'u' and
|
|
||||||
* four hex digits) at position @a pos of @a string_buffer via a nibble
|
|
||||||
* lookup table, avoiding the format-string parsing and locale machinery of
|
|
||||||
* `snprintf`. Advances @a pos by the number of bytes written (6).
|
|
||||||
*
|
|
||||||
* @param[in] pos position in @a string_buffer to write at; there must
|
|
||||||
* be at least 6 bytes of headroom
|
|
||||||
* @param[in] codeunit 16-bit value to encode
|
|
||||||
*/
|
|
||||||
void write_u_escape(std::size_t& pos, std::uint16_t codeunit) noexcept
|
|
||||||
{
|
|
||||||
JSON_ASSERT(string_buffer.size() - pos >= 6);
|
|
||||||
constexpr const char* nibble_to_hex = "0123456789abcdef";
|
|
||||||
string_buffer[pos + 0] = '\\';
|
|
||||||
string_buffer[pos + 1] = 'u';
|
|
||||||
string_buffer[pos + 2] = nibble_to_hex[(codeunit >> 12u) & 0x0Fu];
|
|
||||||
string_buffer[pos + 3] = nibble_to_hex[(codeunit >> 8u) & 0x0Fu];
|
|
||||||
string_buffer[pos + 4] = nibble_to_hex[(codeunit >> 4u) & 0x0Fu];
|
|
||||||
string_buffer[pos + 5] = nibble_to_hex[codeunit & 0x0Fu];
|
|
||||||
pos += 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
// templates to avoid warnings about useless casts
|
// templates to avoid warnings about useless casts
|
||||||
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
||||||
bool is_negative_number(NumberType x)
|
bool is_negative_number(NumberType x)
|
||||||
|
|||||||
@@ -3776,6 +3776,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
return *this == basic_json(rhs);
|
return *this == basic_json(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief comparison: not equal
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||||
|
bool operator!=(const_reference rhs) const noexcept
|
||||||
|
{
|
||||||
|
if (compares_unordered(rhs, true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief comparison: 3-way
|
/// @brief comparison: 3-way
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
||||||
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
||||||
@@ -3881,6 +3892,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||||
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
||||||
{
|
{
|
||||||
|
if (compares_unordered(lhs, rhs, true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2520,11 +2520,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP
|
|||||||
#define JSON_HAS_RANGES 0
|
#define JSON_HAS_RANGES 0
|
||||||
#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
|
#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
|
||||||
#define JSON_HAS_RANGES 0
|
#define JSON_HAS_RANGES 0
|
||||||
// nvcc CUDA 12.0/12.1 chokes on the enable_borrowed_range variable-template
|
|
||||||
// syntax when compiling as CUDA source; fixed in CUDA 12.2 (issue #3907)
|
|
||||||
#elif defined(__CUDACC__) && defined(__CUDACC_VER_MAJOR__) && __CUDACC_VER_MAJOR__ == 12 \
|
|
||||||
&& defined(__CUDACC_VER_MINOR__) && (__CUDACC_VER_MINOR__ == 0 || __CUDACC_VER_MINOR__ == 1)
|
|
||||||
#define JSON_HAS_RANGES 0
|
|
||||||
#elif defined(__cpp_lib_ranges)
|
#elif defined(__cpp_lib_ranges)
|
||||||
#define JSON_HAS_RANGES 1
|
#define JSON_HAS_RANGES 1
|
||||||
#else
|
#else
|
||||||
@@ -7267,7 +7262,7 @@ class wide_string_input_adapter
|
|||||||
|
|
||||||
// parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
|
// parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
|
||||||
template<class T>
|
template<class T>
|
||||||
JSON_HEDLEY_NO_RETURN std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||||
}
|
}
|
||||||
@@ -19967,12 +19962,18 @@ class serializer
|
|||||||
{
|
{
|
||||||
if (codepoint <= 0xFFFF)
|
if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(codepoint));
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
|
||||||
|
static_cast<std::uint16_t>(codepoint)));
|
||||||
|
bytes += 6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)));
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
write_u_escape(bytes, static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
|
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
|
||||||
|
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
|
||||||
|
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
|
||||||
|
bytes += 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -20179,32 +20180,6 @@ class serializer
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* @brief write a lowercase "\uXXXX" escape sequence into @a string_buffer
|
|
||||||
*
|
|
||||||
* Branch-free replacement for `snprintf(buf, 7, "\\u%04x", codeunit)` in the
|
|
||||||
* string escaping hot path. It writes exactly six characters ('\\', 'u' and
|
|
||||||
* four hex digits) at position @a pos of @a string_buffer via a nibble
|
|
||||||
* lookup table, avoiding the format-string parsing and locale machinery of
|
|
||||||
* `snprintf`. Advances @a pos by the number of bytes written (6).
|
|
||||||
*
|
|
||||||
* @param[in] pos position in @a string_buffer to write at; there must
|
|
||||||
* be at least 6 bytes of headroom
|
|
||||||
* @param[in] codeunit 16-bit value to encode
|
|
||||||
*/
|
|
||||||
void write_u_escape(std::size_t& pos, std::uint16_t codeunit) noexcept
|
|
||||||
{
|
|
||||||
JSON_ASSERT(string_buffer.size() - pos >= 6);
|
|
||||||
constexpr const char* nibble_to_hex = "0123456789abcdef";
|
|
||||||
string_buffer[pos + 0] = '\\';
|
|
||||||
string_buffer[pos + 1] = 'u';
|
|
||||||
string_buffer[pos + 2] = nibble_to_hex[(codeunit >> 12u) & 0x0Fu];
|
|
||||||
string_buffer[pos + 3] = nibble_to_hex[(codeunit >> 8u) & 0x0Fu];
|
|
||||||
string_buffer[pos + 4] = nibble_to_hex[(codeunit >> 4u) & 0x0Fu];
|
|
||||||
string_buffer[pos + 5] = nibble_to_hex[codeunit & 0x0Fu];
|
|
||||||
pos += 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
// templates to avoid warnings about useless casts
|
// templates to avoid warnings about useless casts
|
||||||
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
||||||
bool is_negative_number(NumberType x)
|
bool is_negative_number(NumberType x)
|
||||||
@@ -24627,6 +24602,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
return *this == basic_json(rhs);
|
return *this == basic_json(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief comparison: not equal
|
||||||
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||||
|
bool operator!=(const_reference rhs) const noexcept
|
||||||
|
{
|
||||||
|
if (compares_unordered(rhs, true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief comparison: 3-way
|
/// @brief comparison: 3-way
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
||||||
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
||||||
@@ -24732,6 +24718,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||||
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
||||||
{
|
{
|
||||||
|
if (compares_unordered(lhs, rhs, true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,11 +68,7 @@ target_compile_options(test_main PUBLIC
|
|||||||
# Disable warning C4566: character represented by universal-character-name '\uFF01'
|
# Disable warning C4566: character represented by universal-character-name '\uFF01'
|
||||||
# cannot be represented in the current code page (1252)
|
# cannot be represented in the current code page (1252)
|
||||||
# Disable warning C4996: 'nlohmann::basic_json<...>::operator <<': was declared deprecated
|
# Disable warning C4996: 'nlohmann::basic_json<...>::operator <<': was declared deprecated
|
||||||
# Disable warning C4702: unreachable code; wide_string_input_adapter::get_elements()
|
$<$<CXX_COMPILER_ID:MSVC>:/W4;/wd4566;/wd4996;$<$<CONFIG:Release>:/wd4702>>
|
||||||
# is annotated JSON_HEDLEY_NO_RETURN (it always throws), which
|
|
||||||
# makes MSVC flag the code following its call in binary_reader.hpp
|
|
||||||
# as unreachable for that instantiation, in both Debug and Release
|
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:/W4;/wd4566;/wd4996;/wd4702>
|
|
||||||
# https://github.com/nlohmann/json/issues/1114
|
# https://github.com/nlohmann/json/issues/1114
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:/bigobj> $<$<BOOL:${MINGW}>:-Wa,-mbig-obj>
|
$<$<CXX_COMPILER_ID:MSVC>:/bigobj> $<$<BOOL:${MINGW}>:-Wa,-mbig-obj>
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,7 @@ project(json_cuda LANGUAGES CUDA)
|
|||||||
|
|
||||||
add_executable(json_cuda json_cuda.cu)
|
add_executable(json_cuda json_cuda.cu)
|
||||||
target_include_directories(json_cuda PRIVATE ../../include)
|
target_include_directories(json_cuda PRIVATE ../../include)
|
||||||
|
target_compile_features(json_cuda PUBLIC cuda_std_11)
|
||||||
# nvcc added C++20 support in CUDA 12.0 and C++17 in CUDA 11.0; pick the
|
|
||||||
# newest standard the detected compiler actually supports (see #3907)
|
|
||||||
# instead of hard-requiring one standard for every CUDA version.
|
|
||||||
if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
|
|
||||||
set(json_cuda_std 20)
|
|
||||||
elseif(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)
|
|
||||||
set(json_cuda_std 17)
|
|
||||||
else()
|
|
||||||
set(json_cuda_std 11)
|
|
||||||
endif()
|
|
||||||
target_compile_features(json_cuda PUBLIC cuda_std_${json_cuda_std})
|
|
||||||
set_target_properties(json_cuda PROPERTIES
|
set_target_properties(json_cuda PROPERTIES
|
||||||
CUDA_EXTENSIONS OFF
|
CUDA_EXTENSIONS OFF
|
||||||
CUDA_STANDARD_REQUIRED ON
|
CUDA_STANDARD_REQUIRED ON
|
||||||
|
|||||||
@@ -16,20 +16,4 @@ int main()
|
|||||||
// regression for #3013 (ordered_json::reset() compile error with nvcc)
|
// regression for #3013 (ordered_json::reset() compile error with nvcc)
|
||||||
nlohmann::ordered_json metadata;
|
nlohmann::ordered_json metadata;
|
||||||
metadata.erase("key");
|
metadata.erase("key");
|
||||||
|
|
||||||
// exercise comparisons (operator==/operator<=>, gated by
|
|
||||||
// JSON_HAS_THREE_WAY_COMPARISON, independent of JSON_HAS_RANGES) and
|
|
||||||
// range-based iteration (exercises iteration_proxy/ranges machinery
|
|
||||||
// beyond just the enable_borrowed_range specialization) — see #3907
|
|
||||||
nlohmann::json a = {1, 2, 3};
|
|
||||||
nlohmann::json b = {1, 2, 3};
|
|
||||||
static_cast<void>(a == b);
|
|
||||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
|
||||||
static_cast<void>(a <=> b); // *NOPAD*
|
|
||||||
static_cast<void>(a <=> 1); // *NOPAD*
|
|
||||||
#endif
|
|
||||||
for (const auto& element : a)
|
|
||||||
{
|
|
||||||
static_cast<void>(element);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,9 +232,6 @@ TEST_CASE("algorithms")
|
|||||||
// only the first four elements are expected to be sorted, the rest are
|
// only the first four elements are expected to be sorted, the rest are
|
||||||
// unspecified by the standard
|
// unspecified by the standard
|
||||||
const json expected({nullptr, false, true, 3});
|
const json expected({nullptr, false, true, 3});
|
||||||
// std::equal below only bounds-checks the first range; assert the
|
|
||||||
// second range is at least as long to rule out an over-read (CWE-126)
|
|
||||||
CHECK(std::distance(begin(expected), end(expected)) >= 4);
|
|
||||||
CHECK(std::equal(j.begin(), j.begin() + 4, begin(expected)));
|
CHECK(std::equal(j.begin(), j.begin() + 4, begin(expected)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct bad_allocator : std::allocator<T>
|
|||||||
template<class U> bad_allocator(const bad_allocator<U>& /*unused*/) { }
|
template<class U> bad_allocator(const bad_allocator<U>& /*unused*/) { }
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
[[noreturn]] void construct(T* /*unused*/, Args&& ... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward)
|
void construct(T* /*unused*/, Args&& ... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||||
{
|
{
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -322,12 +322,14 @@ TEST_CASE("alternative string type")
|
|||||||
|
|
||||||
SECTION("JSON pointer")
|
SECTION("JSON pointer")
|
||||||
{
|
{
|
||||||
// Direct conversion from a json literal to alt_json is not supported due to issue #3425:
|
// conversion from json to alt_json fails to compile (see #3425);
|
||||||
// alt_json's string_t (alt_string) is not directly constructible from std::string, so the
|
// attempted fix(*) produces: [[['b','a','r'],['b','a','z']]] (with each char being an integer)
|
||||||
// cross-basic_json conversion falls back to the array-conversion path, incorrectly representing
|
// (*) disable implicit conversion for json_refs of any basic_json type
|
||||||
// objects as arrays of [key, value] pairs and strings as arrays of character codes.
|
// alt_json j = R"(
|
||||||
// See https://github.com/nlohmann/json/issues/3425 for details.
|
// {
|
||||||
// Workaround: use alt_json::parse() instead of implicit conversion.
|
// "foo": ["bar", "baz"]
|
||||||
|
// }
|
||||||
|
// )"_json;
|
||||||
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
||||||
|
|
||||||
CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);
|
CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);
|
||||||
|
|||||||
@@ -369,7 +369,6 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
SECTION("comparison: not equal")
|
SECTION("comparison: not equal")
|
||||||
{
|
{
|
||||||
// check that two values compare unequal as expected
|
// check that two values compare unequal as expected
|
||||||
// operator!= now means exactly !(a==b) without special cases for NaN/discarded
|
|
||||||
for (size_t i = 0; i < j_values.size(); ++i)
|
for (size_t i = 0; i < j_values.size(); ++i)
|
||||||
{
|
{
|
||||||
for (size_t j = 0; j < j_values.size(); ++j)
|
for (size_t j = 0; j < j_values.size(); ++j)
|
||||||
@@ -377,12 +376,25 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
CAPTURE(i)
|
CAPTURE(i)
|
||||||
CAPTURE(j)
|
CAPTURE(j)
|
||||||
|
|
||||||
CHECK((j_values[i] != j_values[j]) == !(j_values[i] == j_values[j]));
|
if (json::compares_unordered(j_values[i], j_values[j], true))
|
||||||
|
{
|
||||||
|
// if two values compare unordered,
|
||||||
|
// check that the boolean comparison result is always false
|
||||||
|
CHECK_FALSE(j_values[i] != j_values[j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// otherwise, check that they compare according to their definition
|
||||||
|
// as the inverse of equal
|
||||||
|
CHECK((j_values[i] != j_values[j]) == !(j_values[i] == j_values[j]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare with null pointer
|
// compare with null pointer
|
||||||
const json j_null;
|
const json j_null;
|
||||||
|
CHECK((j_null != nullptr) == false);
|
||||||
|
CHECK((nullptr != j_null) == false);
|
||||||
CHECK((j_null != nullptr) == !(j_null == nullptr));
|
CHECK((j_null != nullptr) == !(j_null == nullptr));
|
||||||
CHECK((nullptr != j_null) == !(nullptr == j_null));
|
CHECK((nullptr != j_null) == !(nullptr == j_null));
|
||||||
}
|
}
|
||||||
@@ -582,34 +594,3 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
|
||||||
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
|
|
||||||
|
|
||||||
TEST_CASE("regression #3868 - heterogeneous comparisons compile under C++20 (P2468R2)")
|
|
||||||
{
|
|
||||||
// Issue #3868: operator!= was preventing compiler from synthesizing reversed
|
|
||||||
// operator== candidates under C++20's P2468R2 rewritten candidate rules.
|
|
||||||
// Verify that heterogeneous comparisons now work.
|
|
||||||
|
|
||||||
SECTION("string vs json")
|
|
||||||
{
|
|
||||||
std::string s = "string";
|
|
||||||
json j = "string";
|
|
||||||
CHECK(s == j);
|
|
||||||
CHECK(j == s);
|
|
||||||
CHECK_FALSE(s != j);
|
|
||||||
CHECK_FALSE(j != s);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("other heterogeneous types")
|
|
||||||
{
|
|
||||||
int i = 42;
|
|
||||||
json j = 42;
|
|
||||||
CHECK(i == j);
|
|
||||||
CHECK(j == i);
|
|
||||||
CHECK_FALSE(i != j);
|
|
||||||
CHECK_FALSE(j != i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ TEST_CASE("constructors")
|
|||||||
const auto t = j.get<std::tuple<int, float, std::string>>();
|
const auto t = j.get<std::tuple<int, float, std::string>>();
|
||||||
CHECK(std::get<0>(t) == j[0]);
|
CHECK(std::get<0>(t) == j[0]);
|
||||||
CHECK(std::get<1>(t) == j[1]);
|
CHECK(std::get<1>(t) == j[1]);
|
||||||
CHECK(std::get<2>(t) == j[2]);
|
// CHECK(std::get<2>(t) == j[2]); // commented out due to CI issue, see https://github.com/nlohmann/json/pull/3985 and https://github.com/nlohmann/json/issues/4025
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::tuple tie")
|
SECTION("std::tuple tie")
|
||||||
|
|||||||
@@ -168,32 +168,6 @@ TEST_CASE("convenience functions")
|
|||||||
CHECK_THROWS_WITH_AS(check_escaped("\xC2"), "[json.exception.type_error.316] incomplete UTF-8 string; last byte: 0xC2", json::type_error&);
|
CHECK_THROWS_WITH_AS(check_escaped("\xC2"), "[json.exception.type_error.316] incomplete UTF-8 string; last byte: 0xC2", json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string escape with ensure_ascii")
|
|
||||||
{
|
|
||||||
// control characters are escaped regardless of ensure_ascii
|
|
||||||
check_escaped("\x01", "\\u0001", true);
|
|
||||||
check_escaped("\x1f", "\\u001f", true);
|
|
||||||
|
|
||||||
// non-ASCII code points in the Basic Multilingual Plane are emitted as
|
|
||||||
// a single lowercase \uXXXX escape (exercises every nibble position)
|
|
||||||
check_escaped("\xC2\x80", "\\u0080", true); // U+0080
|
|
||||||
check_escaped("\xC3\xBF", "\\u00ff", true); // U+00FF (ÿ)
|
|
||||||
check_escaped("\xDF\xBF", "\\u07ff", true); // U+07FF
|
|
||||||
check_escaped("\xE4\xBD\xA0", "\\u4f60", true); // U+4F60 (你)
|
|
||||||
check_escaped("\xEA\xAF\x8D", "\\uabcd", true); // U+ABCD
|
|
||||||
check_escaped("\xEF\xBF\xBD", "\\ufffd", true); // U+FFFD (replacement char, all-f nibbles)
|
|
||||||
|
|
||||||
// code points outside the BMP are emitted as a UTF-16 surrogate pair
|
|
||||||
// of two lowercase \uXXXX escapes
|
|
||||||
check_escaped("\xF0\x90\x80\x80", "\\ud800\\udc00", true); // U+10000 (lowest astral)
|
|
||||||
check_escaped("\xF0\x9F\x98\x80", "\\ud83d\\ude00", true); // U+1F600 (😀)
|
|
||||||
check_escaped("\xF4\x8F\xBF\xBF", "\\udbff\\udfff", true); // U+10FFFF (highest code point)
|
|
||||||
|
|
||||||
// with ensure_ascii disabled, non-ASCII input is passed through verbatim
|
|
||||||
check_escaped("\xE4\xBD\xA0", "\xE4\xBD\xA0", false);
|
|
||||||
check_escaped("\xF0\x9F\x98\x80", "\xF0\x9F\x98\x80", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("string concat")
|
SECTION("string concat")
|
||||||
{
|
{
|
||||||
using nlohmann::detail::concat;
|
using nlohmann::detail::concat;
|
||||||
|
|||||||
@@ -1761,27 +1761,16 @@ TEST_CASE("std::filesystem::path")
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !JSON_USE_IMPLICIT_CONVERSIONS
|
||||||
TEST_CASE("std::optional")
|
TEST_CASE("std::optional")
|
||||||
{
|
{
|
||||||
SECTION("null")
|
SECTION("null")
|
||||||
{
|
{
|
||||||
const json j_null;
|
json j_null;
|
||||||
const std::optional<std::string> opt_null;
|
std::optional<std::string> opt_null;
|
||||||
|
|
||||||
CHECK(json(opt_null) == j_null);
|
CHECK(json(opt_null) == j_null);
|
||||||
CHECK(j_null.get<std::optional<std::string>>() == std::nullopt);
|
CHECK(j_null.get<std::optional<std::string>>() == std::nullopt);
|
||||||
|
|
||||||
// Constructing std::optional<T> directly from JSON null throws because
|
|
||||||
// std::optional's own converting constructor is chosen over basic_json's
|
|
||||||
// operator T(). This is a language-level limitation (std::optional<T> is
|
|
||||||
// constructible from T, and T is constructible from basic_json via the
|
|
||||||
// operator); there is no SFINAE path that distinguishes "call from inside
|
|
||||||
// std::optional's constructor" from "direct call". Use get<std::optional<T>>()
|
|
||||||
// or get_to() instead for correct null handling. See #4864 and #5246.
|
|
||||||
CHECK_THROWS_WITH_AS(std::optional<std::string>(j_null),
|
|
||||||
"[json.exception.type_error.302] type must be string, but is null", json::type_error&);
|
|
||||||
CHECK_THROWS_WITH_AS(std::optional<int>(j_null),
|
|
||||||
"[json.exception.type_error.302] type must be number, but is null", json::type_error&);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
@@ -1830,6 +1819,7 @@ TEST_CASE("std::optional")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JSON_HAS_CPP_17
|
#ifdef JSON_HAS_CPP_17
|
||||||
#undef JSON_HAS_CPP_17
|
#undef JSON_HAS_CPP_17
|
||||||
|
|||||||
@@ -942,7 +942,7 @@ TEST_CASE("iterators 2")
|
|||||||
json j_expected{5, 4, 3, 2, 1};
|
json j_expected{5, 4, 3, 2, 1};
|
||||||
|
|
||||||
auto reversed = j | std::views::reverse;
|
auto reversed = j | std::views::reverse;
|
||||||
CHECK(reversed == j_expected);
|
CHECK(std::ranges::equal(reversed, j_expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("transform")
|
SECTION("transform")
|
||||||
|
|||||||
Vendored
+7115
-5102
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user