Compare commits

..
Author SHA1 Message Date
Niels Lohmann 42a22d2d5e Merge remote-tracking branch 'origin/develop' into fix/develop-ci-after-merges
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 15:01:16 +02:00
Niels Lohmann 45db371915 Regenerate BUILD.bazel and nlohmann_json.natvis
Signed-off-by: Niels Lohmann <mail@nlohmann.me>

#5746 added detail/output/error_handler.hpp and #5741 the json_abi_sbu8 ABI tag.
2026-10-04 14:50:19 +02:00
Niels Lohmann 5d47284e6c Title the macro examples and add JSON_STRICT_BINARY_UTF8 to the docset
The documentation style check requires "Example: ..." titles on pages with several examples (#5741, #5591) and a docset entry for every macro page.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 14:50:19 +02:00
Niels Lohmann 3173c28dac Fix the tests added by the merged PRs for all CI configurations
- discard the results of dump() and from_*() in CHECK_THROWS with
  utils::ignore_return_value (GCC -Werror=unused-result)
- give unit-bson's huge_string_t a default constructor (MSVC C2512,
  GCC 5, clang 3.5)
- unit-disabled_exceptions: use the literals namespace when the global
  UDLs are off (ci_test_noglobaludls; #5700)
- unit-binary_utf8_strict: expect the JSON pointer prefix with
  JSON_DIAGNOSTICS (#5741)
- skip the tests that rely on exceptions under JSON_NOEXCEPTION
  (#5678, #5732)
- clang-tidy and clang -Werror: static test data, CAPTURE(...);,
  const-correctness, use-after-move alias, unused conversion operator,
  a missing <iterator> include

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 14:50:18 +02:00
Niels Lohmann e8239afff1 Split unit-conversions.cpp so MinGW can link it
clang 18 with the MinGW linker failed to link test-conversions_cpp17
("relocation truncated to fit: IMAGE_REL_AMD64_REL32"). As windows.yml
recommends, keep the objects small by splitting the test file.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 14:49:52 +02:00
Niels Lohmann fd0261d909 Fix the library warnings and noexcept specifications from the merged PRs
- binary_reader: rename the error_handler constructor parameter, which
  shadowed the member (-Wshadow, -Wshadow-field-in-constructor; #5746)
- basic_json(copy_construct_tag, ...): declare it noexcept when copying
  the base class is (GCC 16 -Wnoexcept; #5690)
- the scalar-on-left legacy comparison operators: noexcept only when
  converting the scalar is, like their member counterparts (#5682, #5751)
- compare_leaves: use std::is_eq/is_lt/is_gt instead of comparing a
  std::partial_ordering with 0 (-Wzero-as-null-pointer-constant; #5686)
- serializer: silence MSVC C4127 for the EnsureAscii template parameter
  (#5741, #5746)
- clang-tidy: return the sanitized reference in binary_writer, take the
  key of ordered_map::find_impl by const reference (#5727), and mark the
  switches over parse_array_index (#5728)
- ordered_map: keep <memory> for std::allocator (IWYU)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 14:49:51 +02:00
Niels Lohmann fa2465b325 Fix the remaining CI failures on develop
- unit-wstring: with a 16-bit wchar_t (Windows), a lone surrogate is
  reported as the ill-formed byte 0xFF since #5704; the std::wstring
  expectations still had the previous <U+0000>.
- ci_single_binaries: json_literals.hpp (#5610) and json.hpp include each
  other on purpose, and IWYU, not following the cycle, asks to replace
  json.hpp with json_fwd.hpp. Report its findings without failing the
  build, as already done for json.hpp.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 12:23:10 +02:00
Niels Lohmann ee7c0ce71c Merge remote-tracking branch 'origin/develop' into fix/develop-ci-after-merges 2026-10-04 12:17:08 +02:00
Niels Lohmann 2b29ca1812 Keep the serializer conversion for objects whose keys cannot be converted
#5591 added a test converting nlohmann::json into a basic_json whose
string type cannot be constructed from std::string. That instantiates
convert_iteratively(), whose members.emplace_back(next.key(), ...) needs
exactly that key conversion, and broke the build of unit-alt-string.
Dispatch on the key's constructibility and leave such conversions to the
serializers, as the levels above the nesting bound already do (#3425).

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 12:04:35 +02:00
52 changed files with 4977 additions and 1886 deletions
+1 -1
View File
@@ -107,7 +107,7 @@ jobs:
container: ubuntu:24.04 container: ubuntu:24.04
strategy: strategy:
matrix: matrix:
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_delete_deprecated_functions, ci_test_no_thread_local] target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_no_thread_local]
steps: steps:
- name: Install build-essential - name: Install build-essential
run: apt-get update ; apt-get install -y build-essential unzip wget git run: apt-get update ; apt-get install -y build-essential unzip wget git
+1
View File
@@ -57,6 +57,7 @@ cc_library(
"include/nlohmann/detail/meta/type_traits.hpp", "include/nlohmann/detail/meta/type_traits.hpp",
"include/nlohmann/detail/meta/void_t.hpp", "include/nlohmann/detail/meta/void_t.hpp",
"include/nlohmann/detail/output/binary_writer.hpp", "include/nlohmann/detail/output/binary_writer.hpp",
"include/nlohmann/detail/output/error_handler.hpp",
"include/nlohmann/detail/output/output_adapters.hpp", "include/nlohmann/detail/output/output_adapters.hpp",
"include/nlohmann/detail/output/serializer.hpp", "include/nlohmann/detail/output/serializer.hpp",
"include/nlohmann/detail/recursion_depth_limit.hpp", "include/nlohmann/detail/recursion_depth_limit.hpp",
-6
View File
@@ -62,7 +62,6 @@ option(JSON_MultipleHeaders "Use non-amalgamated version of the l
option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF)
option(JSON_StrictNulHandling "Build with strict NUL-byte handling enabled." OFF) option(JSON_StrictNulHandling "Build with strict NUL-byte handling enabled." OFF)
option(JSON_StrictBinaryUTF8 "Build with UTF-8 checks in the CBOR, UBJSON, BJData, and BSON writers enabled." OFF) option(JSON_StrictBinaryUTF8 "Build with UTF-8 checks in the CBOR, UBJSON, BJData, and BSON writers enabled." OFF)
option(JSON_DeleteDeprecatedFunctions "Delete the deprecated functions instead of only deprecating them." OFF)
if (JSON_CI) if (JSON_CI)
include(ci) include(ci)
@@ -124,10 +123,6 @@ if (JSON_StrictBinaryUTF8)
message(STATUS "Strict UTF-8 checks in binary writers enabled (JSON_STRICT_BINARY_UTF8=1)") message(STATUS "Strict UTF-8 checks in binary writers enabled (JSON_STRICT_BINARY_UTF8=1)")
endif() endif()
if (JSON_DeleteDeprecatedFunctions)
message(STATUS "Deprecated functions are deleted (JSON_DELETE_DEPRECATED_FUNCTIONS=1)")
endif()
if (JSON_Diagnostic_Positions) if (JSON_Diagnostic_Positions)
message(STATUS "Diagnostic positions enabled (JSON_DIAGNOSTIC_POSITIONS=1)") message(STATUS "Diagnostic positions enabled (JSON_DIAGNOSTIC_POSITIONS=1)")
endif() endif()
@@ -164,7 +159,6 @@ target_compile_definitions(
$<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1> $<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
$<$<BOOL:${JSON_StrictNulHandling}>:JSON_STRICT_NUL_HANDLING=1> $<$<BOOL:${JSON_StrictNulHandling}>:JSON_STRICT_NUL_HANDLING=1>
$<$<BOOL:${JSON_StrictBinaryUTF8}>:JSON_STRICT_BINARY_UTF8=1> $<$<BOOL:${JSON_StrictBinaryUTF8}>:JSON_STRICT_BINARY_UTF8=1>
$<$<BOOL:${JSON_DeleteDeprecatedFunctions}>:JSON_DELETE_DEPRECATED_FUNCTIONS=1>
) )
target_include_directories( target_include_directories(
+8 -18
View File
@@ -249,20 +249,6 @@ add_custom_target(ci_test_strict_nul_handling
COMMENT "Compile and test with strict NUL-byte handling enabled" COMMENT "Compile and test with strict NUL-byte handling enabled"
) )
###############################################################################
# Delete the deprecated functions.
###############################################################################
add_custom_target(ci_test_delete_deprecated_functions
COMMAND ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_DeleteDeprecatedFunctions=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_delete_deprecated_functions
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_delete_deprecated_functions
COMMAND cd ${PROJECT_BINARY_DIR}/build_delete_deprecated_functions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
COMMENT "Compile and test with the deprecated functions deleted"
)
############################################################################### ###############################################################################
# Disable global UDLs. # Disable global UDLs.
############################################################################### ###############################################################################
@@ -610,8 +596,9 @@ foreach(SRC_FILE ${SRC_FILES})
add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp) add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp)
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include) target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11) target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
if(RELATIVE_SRC_FILE STREQUAL "json") if(RELATIVE_SRC_FILE STREQUAL "json" OR RELATIVE_SRC_FILE STREQUAL "json_literals")
# see below: report json.hpp's diagnostics without --error, so they do not fail the build # see below: report the diagnostics of json.hpp and json_literals.hpp without --error, so they
# do not fail the build
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${IWYU_TOOL} -Xiwyu --max_line_length=300) set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${IWYU_TOOL} -Xiwyu --max_line_length=300)
else() else()
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}") set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
@@ -625,7 +612,10 @@ foreach(SRC_FILE ${SRC_FILES})
# reporting its diagnostics (informational, via CXX_INCLUDE_WHAT_YOU_USE above) but exclude it # reporting its diagnostics (informational, via CXX_INCLUDE_WHAT_YOU_USE above) but exclude it
# from the hard gate below so a fresh IWYU/compiler combination does not fail this target on a # from the hard gate below so a fresh IWYU/compiler combination does not fail this target on a
# nondeterministic suggestion for a header that already re-exports everything on purpose. # nondeterministic suggestion for a header that already re-exports everything on purpose.
if(NOT RELATIVE_SRC_FILE STREQUAL "json") # json_literals.hpp and json.hpp include each other on purpose (json.hpp includes it at its end
# unless JSON_NO_AUTOMATIC_UDLS is defined), and IWYU, not following the cycle, suggests replacing
# json.hpp with json_fwd.hpp although the literals need the complete basic_json; exclude it, too.
if(NOT RELATIVE_SRC_FILE STREQUAL "json" AND NOT RELATIVE_SRC_FILE STREQUAL "json_literals")
list(APPEND single_binaries_tus src_single/${RELATIVE_SRC_FILE}.cpp) list(APPEND single_binaries_tus src_single/${RELATIVE_SRC_FILE}.cpp)
endif() endif()
endforeach() endforeach()
@@ -715,7 +705,7 @@ ci_get_cmake(4.0.0 CMAKE_4_0_0_BINARY)
# the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0 # the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind
JSON_StrictNulHandling JSON_StrictBinaryUTF8 JSON_DeleteDeprecatedFunctions) JSON_StrictNulHandling JSON_StrictBinaryUTF8)
set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0}) set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0}) set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
-1
View File
@@ -219,7 +219,6 @@ INSERT INTO searchIndex(name, type, path) VALUES ('Supported Macros', 'Guide', '
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'api/macros/json_assert/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'api/macros/json_assert/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_BRACE_INIT_COPY_SEMANTICS', 'Macro', 'api/macros/json_brace_init_copy_semantics/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_BRACE_INIT_COPY_SEMANTICS', 'Macro', 'api/macros/json_brace_init_copy_semantics/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'api/macros/json_throw_user/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'api/macros/json_throw_user/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DELETE_DEPRECATED_FUNCTIONS', 'Macro', 'api/macros/json_delete_deprecated_functions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'api/macros/json_diagnostics/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'api/macros/json_diagnostics/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTIC_POSITIONS', 'Macro', 'api/macros/json_diagnostic_positions/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTIC_POSITIONS', 'Macro', 'api/macros/json_diagnostic_positions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'api/macros/json_disable_enum_serialization/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'api/macros/json_disable_enum_serialization/index.html');
@@ -120,12 +120,3 @@ Linear in the size of the input.
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0. - Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0. - Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
- Added `error_handler` parameter in version 3.13.0. - Added `error_handler` parameter in version 3.13.0.
!!! warning "Deprecation"
- Overload (2) replaces calls to `from_bjdata` with a pointer and a length as first two parameters, which has been
deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
`#!cpp from_bjdata(ptr, len, ...);` with `#!cpp from_bjdata(ptr, ptr+len, ...);`.
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
function.
@@ -106,12 +106,3 @@ Linear in the size of the input.
## Version history ## Version history
- Added in version 3.13.0. - Added in version 3.13.0.
!!! warning "Deprecation"
- Overload (2) replaces calls to `from_bon8` with a pointer and a length as first two parameters, which has been
deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
`#!cpp from_bon8(ptr, len, ...);` with `#!cpp from_bon8(ptr, ptr+len, ...);`.
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
function.
-5
View File
@@ -59,11 +59,6 @@ header. See also the [macro overview page](../../features/macros.md).
- [**JSON_DISABLE_TUPLE_REFERENCE_CONVERSION**](json_disable_tuple_reference_conversion.md) - switch off conversion from a one-element tuple of a JSON reference - [**JSON_DISABLE_TUPLE_REFERENCE_CONVERSION**](json_disable_tuple_reference_conversion.md) - switch off conversion from a one-element tuple of a JSON reference
- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions - [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions
## Deprecated functions
- [**JSON_DELETE_DEPRECATED_FUNCTIONS**](json_delete_deprecated_functions.md) - opt in to deleting the deprecated
functions ahead of their removal in version 4.0.0
## Comparison behavior ## Comparison behavior
- [**JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON**](json_use_legacy_discarded_value_comparison.md) - - [**JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON**](json_use_legacy_discarded_value_comparison.md) -
@@ -1,96 +0,0 @@
# JSON_DELETE_DEPRECATED_FUNCTIONS
```cpp
#define JSON_DELETE_DEPRECATED_FUNCTIONS /* value */
```
When defined to `1`, all [deprecated functions](../../community/roadmap.md#removal-of-deprecated-functions) of the
library are declared as deleted (`= delete`) instead of only being marked as deprecated. Code that still calls one of
them no longer compiles. This way, you can find all calls that need to be replaced before version 4.0.0 removes these
functions; the [migration guide](../../integration/migration_guide.md#replace-deprecated-functions) describes how.
A deleted function, unlike a removed one, still takes part in overload resolution. A call that would select it
therefore fails to compile instead of silently selecting another overload. This matters for the deprecated
`from_*(ptr, len)` overloads of [`from_cbor`](../basic_json/from_cbor.md), [`from_msgpack`](../basic_json/from_msgpack.md),
[`from_ubjson`](../basic_json/from_ubjson.md), [`from_bjdata`](../basic_json/from_bjdata.md),
[`from_bon8`](../basic_json/from_bon8.md), and [`from_bson`](../basic_json/from_bson.md): without them, a call like
`from_cbor(ptr, len)` would compile, read `ptr` as a NUL-terminated string, and convert `len` to the `strict` parameter.
The macro does not affect the deprecated legacy comparison of discarded values, which is controlled by
[`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](json_use_legacy_discarded_value_comparison.md).
## Default definition
The default value is `0` (disabled, the deprecated functions can still be called, and the compiler warns about it).
```cpp
#define JSON_DELETE_DEPRECATED_FUNCTIONS 0
```
## Notes
!!! info "CMake option"
The macro can also be set with the CMake option
[`JSON_DeleteDeprecatedFunctions`](../../integration/cmake.md#json_deletedeprecatedfunctions) (`OFF` by default).
!!! warning "Opt-in only"
This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no
effect. Define it for the whole project to avoid different declarations of the same class in different
translation units.
!!! note "ABI compatibility"
The macro only turns calls that compile into calls that do not; it does not change the layout or the behavior of
any type. Its value is therefore not encoded in the [namespace](../../features/namespace.md).
## Examples
??? example "Example: default behavior (macro not defined)"
Without the macro, the deprecated overload is called, and the compiler warns about it:
```cpp
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
const std::vector<std::uint8_t> v = {0x82, 0x01, 0x02};
auto j = json::from_cbor(v.data(), v.size());
// warning: 'from_cbor' is deprecated: Since 3.8.0; use from_cbor(ptr, ptr + len)
}
```
??? example "Example: deleted deprecated functions (macro defined to 1)"
With the macro, the call does not compile:
```cpp
#define JSON_DELETE_DEPRECATED_FUNCTIONS 1
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
const std::vector<std::uint8_t> v = {0x82, 0x01, 0x02};
auto j = json::from_cbor(v.data(), v.size());
// error: call to deleted function 'from_cbor'
}
```
## See also
- [Roadmap: removal of deprecated functions](../../community/roadmap.md#removal-of-deprecated-functions) - the
deprecated functions and the version they were deprecated in
- [Migration guide: replace deprecated functions](../../integration/migration_guide.md#replace-deprecated-functions) -
how to replace each deprecated function
## Version history
- Added in version 3.13.0.
- Planned to be removed in version 4.0.0, which removes the deprecated functions. The deprecated `from_*(ptr, len)`
overloads stay deleted in version 4.0.0.
@@ -112,4 +112,3 @@ The default value is `0` (disabled — existing behavior is preserved).
## Version history ## Version history
- Added in version 3.13.0. - Added in version 3.13.0.
- Planned to become the default (with the macro removed) in version 4.0.0.
@@ -44,7 +44,7 @@ By default, implicit conversions are enabled.
## Examples ## Examples
??? example "Example: implicit and explicit conversions" ??? example "Example: implicit conversion"
This is an example for an implicit conversion: This is an example for an implicit conversion:
+2 -12
View File
@@ -64,8 +64,6 @@ The following macros guard changes that are planned to become the default in ver
| [`JSON_PRECISE_STREAM_POSITION`](../api/macros/json_precise_stream_position.md) | `0` | `1`: reading from a stream does not consume the character after a number | – | 3.13.0 | | [`JSON_PRECISE_STREAM_POSITION`](../api/macros/json_precise_stream_position.md) | `0` | `1`: reading from a stream does not consume the character after a number | – | 3.13.0 |
| [`JSON_STRICT_NUL_HANDLING`](../api/macros/json_strict_nul_handling.md) | `0` | `1`: a NUL byte in the input is a parse error instead of the end of input | [`JSON_StrictNulHandling`](../integration/cmake.md#json_strictnulhandling) | 3.13.0 | | [`JSON_STRICT_NUL_HANDLING`](../api/macros/json_strict_nul_handling.md) | `0` | `1`: a NUL byte in the input is a parse error instead of the end of input | [`JSON_StrictNulHandling`](../integration/cmake.md#json_strictnulhandling) | 3.13.0 |
| [`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md) | `0` | `1`: `to_cbor`, `to_ubjson`, `to_bjdata`, and `to_bson` throw for strings that are not valid UTF-8 by default | [`JSON_StrictBinaryUTF8`](../integration/cmake.md#json_strictbinaryutf8) | 3.13.0 | | [`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md) | `0` | `1`: `to_cbor`, `to_ubjson`, `to_bjdata`, and `to_bson` throw for strings that are not valid UTF-8 by default | [`JSON_StrictBinaryUTF8`](../integration/cmake.md#json_strictbinaryutf8) | 3.13.0 |
| [`JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md) | `0` | `1`: a `basic_json` value can no longer be created from a one-element tuple of a reference to it, such as `std::forward_as_tuple(j)`| [`JSON_DisableTupleReferenceConversion`](../integration/cmake.md#json_disabletuplereferenceconversion) | 3.13.0 |
| [`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md) | `0` | removed: the deprecated functions are removed (see below); the `from_*(ptr, len)` overloads stay deleted | [`JSON_DeleteDeprecatedFunctions`](../integration/cmake.md#json_deletedeprecatedfunctions) | 3.13.0 |
For example, the following makes a 3.x release behave like version 4.0 with respect to these changes: For example, the following makes a 3.x release behave like version 4.0 with respect to these changes:
@@ -77,8 +75,6 @@ For example, the following makes a 3.x release behave like version 4.0 with resp
#define JSON_PRECISE_STREAM_POSITION 1 #define JSON_PRECISE_STREAM_POSITION 1
#define JSON_STRICT_NUL_HANDLING 1 #define JSON_STRICT_NUL_HANDLING 1
#define JSON_STRICT_BINARY_UTF8 1 #define JSON_STRICT_BINARY_UTF8 1
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 1
#define JSON_DELETE_DEPRECATED_FUNCTIONS 1
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
``` ```
@@ -88,13 +84,8 @@ way to achieve this.
### Removal of deprecated functions ### Removal of deprecated functions
Version 4.0 will remove all deprecated functions. Compiling with deprecation warnings enabled shows which of them your Version 4.0 will remove all deprecated functions. Compiling with deprecation warnings enabled shows which of them your
code still uses. Defining [`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md) to code still uses. The [migration guide](../integration/migration_guide.md#replace-deprecated-functions) shows how to
`1` turns these warnings into errors, as the deprecated functions are then deleted. The replace each of them.
[migration guide](../integration/migration_guide.md#replace-deprecated-functions) shows how to replace each of them.
The `from_*` overloads taking a pointer and a length are not removed in version 4.0, but stay deleted. Without them, a
call like `from_cbor(ptr, len)` would still compile: it would read `ptr` as a NUL-terminated string and convert `len`
to the `strict` parameter.
| Deprecated | Since | Migration | | Deprecated | Since | Migration |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------------------------------------------------------------------------------| |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------------------------------------------------------------------------------|
@@ -106,7 +97,6 @@ to the `strict` parameter.
| [`json_pointer::operator string_t`](../api/json_pointer/operator_string_t.md) | 3.11.0 | [JSON Pointers](../integration/migration_guide.md#json-pointers) | | [`json_pointer::operator string_t`](../api/json_pointer/operator_string_t.md) | 3.11.0 | [JSON Pointers](../integration/migration_guide.md#json-pointers) |
| [`json_pointer`](../api/json_pointer/index.md) with a `basic_json` type as template argument, and the overloads of `value`, `contains`, `operator[]`, and `at` accepting such a pointer | 3.11.0 | [JSON Pointers](../integration/migration_guide.md#json-pointers) | | [`json_pointer`](../api/json_pointer/index.md) with a `basic_json` type as template argument, and the overloads of `value`, `contains`, `operator[]`, and `at` accepting such a pointer | 3.11.0 | [JSON Pointers](../integration/migration_guide.md#json-pointers) |
| Comparing a [`json_pointer`](../api/json_pointer/index.md) with a string via [`operator==`](../api/json_pointer/operator_eq.md) or [`operator!=`](../api/json_pointer/operator_ne.md) | 3.11.2 | [JSON Pointers](../integration/migration_guide.md#json-pointers) | | Comparing a [`json_pointer`](../api/json_pointer/index.md) with a string via [`operator==`](../api/json_pointer/operator_eq.md) or [`operator!=`](../api/json_pointer/operator_ne.md) | 3.11.2 | [JSON Pointers](../integration/migration_guide.md#json-pointers) |
| [`from_bjdata`](../api/basic_json/from_bjdata.md) and [`from_bon8`](../api/basic_json/from_bon8.md) with `(ptr, len)` | 3.13.0 | [Parsing](../integration/migration_guide.md#parsing) |
The deprecated legacy comparison of discarded values is controlled by a macro and therefore listed in the table above. The deprecated legacy comparison of discarded values is controlled by a macro and therefore listed in the table above.
+1 -13
View File
@@ -23,17 +23,6 @@ This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/
See [full documentation of `JSON_CATCH_USER(exception)`](../api/macros/json_throw_user.md). See [full documentation of `JSON_CATCH_USER(exception)`](../api/macros/json_throw_user.md).
## `JSON_DELETE_DEPRECATED_FUNCTIONS`
When defined to `1`, all deprecated functions are declared as deleted instead of only being marked as deprecated, so
code that still calls them no longer compiles. This way, you can find all calls that need to be replaced before version
4.0.0 removes these functions.
The macro can also be set with the CMake option
[`JSON_DeleteDeprecatedFunctions`](../integration/cmake.md#json_deletedeprecatedfunctions) (`OFF` by default).
See [full documentation of `JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md).
## `JSON_DIAGNOSTICS` ## `JSON_DIAGNOSTICS`
This macro enables extended diagnostics for exception messages. Possible values are `1` to enable or `0` to disable This macro enables extended diagnostics for exception messages. Possible values are `1` to enable or `0` to disable
@@ -97,8 +86,7 @@ See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json
## `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION` ## `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`
When defined to `1`, a JSON value can no longer be created from a one-element `std::tuple` holding a reference to a JSON When defined to `1`, a JSON value can no longer be created from a one-element `std::tuple` holding a reference to a JSON
value, such as the result of `std::forward_as_tuple(j)`. This lets `std::tuple` convert such tuples element-wise. This value, such as the result of `std::forward_as_tuple(j)`. This lets `std::tuple` convert such tuples element-wise.
is planned to become the default in version 4.0.0.
See [full documentation of `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md). See [full documentation of `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md).
-6
View File
@@ -132,12 +132,6 @@ Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/
Enable CI build targets. The exact targets are used during the several CI steps and are subject to change without notice. This option is `OFF` by default. Enable CI build targets. The exact targets are used during the several CI steps and are subject to change without notice. This option is `OFF` by default.
### `JSON_DeleteDeprecatedFunctions`
Delete the deprecated functions instead of only deprecating them by defining the macro
[`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md). This option is `OFF` by
default.
### `JSON_Diagnostics` ### `JSON_Diagnostics`
Enable [extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) by defining macro [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This option is `OFF` by default. Enable [extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) by defining macro [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This option is `OFF` by default.
@@ -14,13 +14,6 @@ deprecations are annotated with
[`HEDLEY_DEPRECATED_FOR`](https://nemequ.github.io/hedley/api-reference.html#HEDLEY_DEPRECATED_FOR) to report which [`HEDLEY_DEPRECATED_FOR`](https://nemequ.github.io/hedley/api-reference.html#HEDLEY_DEPRECATED_FOR) to report which
function to use instead. function to use instead.
!!! tip "Find all calls of deprecated functions"
Define [`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md) to `1` (or set the
CMake option [`JSON_DeleteDeprecatedFunctions`](cmake.md#json_deletedeprecatedfunctions)) to delete all deprecated
functions. Every remaining call then fails to compile, even if deprecation warnings are disabled, so your code is
ready for version 4.0.0 once it compiles with the macro.
### Parsing ### Parsing
- Function `friend std::istream& operator<<(basic_json&, std::istream&)` is deprecated since 3.0.0. Please use - Function `friend std::istream& operator<<(basic_json&, std::istream&)` is deprecated since 3.0.0. Please use
@@ -48,10 +41,8 @@ function to use instead.
[`from_ubjson`](../api/basic_json/from_ubjson.md), and [`from_bson`](../api/basic_json/from_bson.md)) via initializer [`from_ubjson`](../api/basic_json/from_ubjson.md), and [`from_bson`](../api/basic_json/from_bson.md)) via initializer
lists is deprecated since 3.8.0. Instead, pass two iterators; for instance, call `from_cbor(ptr, ptr+len)` instead of lists is deprecated since 3.8.0. Instead, pass two iterators; for instance, call `from_cbor(ptr, ptr+len)` instead of
`from_cbor({ptr, len})`. Likewise, passing a pointer and a length as two separate arguments to `from_cbor`, `from_cbor({ptr, len})`. Likewise, passing a pointer and a length as two separate arguments to `from_cbor`,
`from_msgpack`, `from_ubjson`, and `from_bson` is deprecated since 3.8.0, and to `from_msgpack`, `from_ubjson`, and `from_bson` is deprecated since 3.8.0; call `from_cbor(ptr, ptr+len)` instead of
[`from_bjdata`](../api/basic_json/from_bjdata.md) and [`from_bon8`](../api/basic_json/from_bon8.md) since 3.13.0; call `from_cbor(ptr, len)`.
`from_cbor(ptr, ptr+len)` instead of `from_cbor(ptr, len)`. These overloads will not be removed in version 4.0.0, but
deleted, so a call like `from_cbor(ptr, len)` cannot compile and convert `len` to the `strict` parameter.
=== "Deprecated" === "Deprecated"
-1
View File
@@ -292,7 +292,6 @@ nav:
- 'JSON_BRACE_INIT_COPY_SEMANTICS': api/macros/json_brace_init_copy_semantics.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_CATCH_USER, JSON_THROW_USER, JSON_TRY_USER': api/macros/json_throw_user.md
- 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md - 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md
- 'JSON_DELETE_DEPRECATED_FUNCTIONS': api/macros/json_delete_deprecated_functions.md
- 'JSON_DIAGNOSTIC_POSITIONS': api/macros/json_diagnostic_positions.md - 'JSON_DIAGNOSTIC_POSITIONS': api/macros/json_diagnostic_positions.md
- 'JSON_DISABLE_ENUM_SERIALIZATION': api/macros/json_disable_enum_serialization.md - 'JSON_DISABLE_ENUM_SERIALIZATION': api/macros/json_disable_enum_serialization.md
- 'JSON_DISABLE_TUPLE_REFERENCE_CONVERSION': api/macros/json_disable_tuple_reference_conversion.md - 'JSON_DISABLE_TUPLE_REFERENCE_CONVERSION': api/macros/json_disable_tuple_reference_conversion.md
@@ -110,15 +110,15 @@ class binary_reader
@param[in] adapter input adapter to read from @param[in] adapter input adapter to read from
@param[in] format the binary format to parse @param[in] format the binary format to parse
@param[in] error_handler how to treat text strings and object keys that @param[in] error_handler_ how to treat text strings and object keys that
are not well-formed UTF-8; none of the supported formats are not well-formed UTF-8; none of the supported formats
requires a decoder to reject those, so the default is to requires a decoder to reject those, so the default is to
@ref error_handler_t::keep them unchanged, as every binary @ref error_handler_t::keep them unchanged, as every binary
reader did before this parameter existed reader did before this parameter existed
*/ */
explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json, explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json,
const error_handler_t error_handler = error_handler_t::keep) noexcept const error_handler_t error_handler_ = error_handler_t::keep) noexcept
: ia(std::move(adapter)), input_format(format), error_handler(error_handler) : ia(std::move(adapter)), input_format(format), error_handler(error_handler_)
{ {
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
} }
+4 -28
View File
@@ -79,15 +79,11 @@ class json_pointer
/// @brief return a string representation of the JSON pointer /// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string_t/ /// @sa https://json.nlohmann.me/api/json_pointer/operator_string_t/
#if JSON_DELETE_DEPRECATED_FUNCTIONS
operator string_t() const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
operator string_t() const operator string_t() const
{ {
return to_string(); return to_string();
} }
#endif
#ifndef JSON_NO_IO #ifndef JSON_NO_IO
/// @brief write string representation of the JSON pointer to stream /// @brief write string representation of the JSON pointer to stream
@@ -326,6 +322,8 @@ class json_pointer
typename BasicJsonType::size_type idx{}; typename BasicJsonType::size_type idx{};
switch (parse_array_index<BasicJsonType>(s, idx)) switch (parse_array_index<BasicJsonType>(s, idx))
{ {
// the branches differ in their messages, not after JSON_THROW's expansion
// NOLINTNEXTLINE(bugprone-branch-clone)
case array_index_status::leading_zero: case array_index_status::leading_zero:
JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
case array_index_status::not_a_number: case array_index_status::not_a_number:
@@ -689,6 +687,8 @@ class json_pointer
typename BasicJsonType::size_type idx{}; typename BasicJsonType::size_type idx{};
switch (parse_array_index<BasicJsonType>(reference_token, idx)) switch (parse_array_index<BasicJsonType>(reference_token, idx))
{ {
// the branches differ in their messages, not after JSON_THROW's expansion
// NOLINTNEXTLINE(bugprone-branch-clone)
case array_index_status::leading_zero: case array_index_status::leading_zero:
JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", reference_token, "' must not begin with '0'"), nullptr)); JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", reference_token, "' must not begin with '0'"), nullptr));
case array_index_status::not_a_number: case array_index_status::not_a_number:
@@ -1020,15 +1020,11 @@ class json_pointer
/// @brief compares JSON pointer and string for equality /// @brief compares JSON pointer and string for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
#if JSON_DELETE_DEPRECATED_FUNCTIONS
bool operator==(const string_t& rhs) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
bool operator==(const string_t& rhs) const bool operator==(const string_t& rhs) const
{ {
return *this == json_pointer(rhs); return *this == json_pointer(rhs);
} }
#endif
/// @brief 3-way compares two JSON pointers /// @brief 3-way compares two JSON pointers
template<typename RefStringTypeRhs> template<typename RefStringTypeRhs>
@@ -1103,31 +1099,21 @@ inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
template<typename RefStringTypeLhs, template<typename RefStringTypeLhs,
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) const StringType& rhs)
{ {
return lhs == json_pointer<RefStringTypeLhs>(rhs); return lhs == json_pointer<RefStringTypeLhs>(rhs);
} }
#endif
template<typename RefStringTypeRhs, template<typename RefStringTypeRhs,
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator==(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
inline bool operator==(const StringType& lhs, inline bool operator==(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) const json_pointer<RefStringTypeRhs>& rhs)
{ {
return json_pointer<RefStringTypeRhs>(lhs) == rhs; return json_pointer<RefStringTypeRhs>(lhs) == rhs;
} }
#endif
template<typename RefStringTypeLhs, typename RefStringTypeRhs> template<typename RefStringTypeLhs, typename RefStringTypeRhs>
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
@@ -1138,31 +1124,21 @@ inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
template<typename RefStringTypeLhs, template<typename RefStringTypeLhs,
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) const StringType& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
#endif
template<typename RefStringTypeRhs, template<typename RefStringTypeRhs,
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator!=(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
inline bool operator!=(const StringType& lhs, inline bool operator!=(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) const json_pointer<RefStringTypeRhs>& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
#endif
template<typename RefStringTypeLhs, typename RefStringTypeRhs> template<typename RefStringTypeLhs, typename RefStringTypeRhs>
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
-4
View File
@@ -888,10 +888,6 @@
#define JSON_DISABLE_ENUM_SERIALIZATION 0 #define JSON_DISABLE_ENUM_SERIALIZATION 0
#endif #endif
#ifndef JSON_DELETE_DEPRECATED_FUNCTIONS
#define JSON_DELETE_DEPRECATED_FUNCTIONS 0
#endif
#ifndef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION #ifndef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 0 #define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 0
#endif #endif
@@ -43,7 +43,6 @@
#undef JSON_PRECISE_STREAM_POSITION #undef JSON_PRECISE_STREAM_POSITION
#undef JSON_STRICT_NUL_HANDLING #undef JSON_STRICT_NUL_HANDLING
#undef JSON_STRICT_BINARY_UTF8 #undef JSON_STRICT_BINARY_UTF8
#undef JSON_DELETE_DEPRECATED_FUNCTIONS
#endif #endif
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp> #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
@@ -2260,18 +2260,18 @@ class binary_writer
switch (error_handler) switch (error_handler)
{ {
case error_handler_t::keep: case error_handler_t::keep:
return s; return s; // NOLINT(bugprone-return-const-ref-from-parameter): callers pass lvalues that outlive the call
case error_handler_t::strict: case error_handler_t::strict:
check_utf8(s, context); check_utf8(s, context);
return s; return s; // NOLINT(bugprone-return-const-ref-from-parameter): callers pass lvalues that outlive the call
case error_handler_t::replace: case error_handler_t::replace:
case error_handler_t::ignore: case error_handler_t::ignore:
default: default:
if (is_valid_utf8(s)) if (is_valid_utf8(s))
{ {
return s; return s; // NOLINT(bugprone-return-const-ref-from-parameter): callers pass lvalues that outlive the call
} }
storage = sanitize_utf8(s, error_handler); storage = sanitize_utf8(s, error_handler);
return storage; return storage;
@@ -706,6 +706,11 @@ class serializer
@a ensure_ascii is a template parameter here so that the branch on it is @a ensure_ascii is a template parameter here so that the branch on it is
resolved once, outside the loop; see @ref dump_escaped. resolved once, outside the loop; see @ref dump_escaped.
*/ */
#ifdef JSON_HEDLEY_MSVC_VERSION
#pragma warning(push)
// EnsureAscii is a template parameter; C++11 has no if constexpr
#pragma warning(disable : 4127) // conditional expression is constant
#endif
template<bool EnsureAscii> template<bool EnsureAscii>
void dump_escaped_impl(const string_t& s) void dump_escaped_impl(const string_t& s)
{ {
@@ -1055,6 +1060,9 @@ class serializer
} }
} }
} }
#ifdef JSON_HEDLEY_MSVC_VERSION
#pragma warning(pop)
#endif
private: private:
/*! /*!
+36 -167
View File
@@ -1048,6 +1048,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
never name it to call this constructor itself. never name it to call this constructor itself.
*/ */
basic_json(copy_construct_tag /*unused*/, const basic_json& src) basic_json(copy_construct_tag /*unused*/, const basic_json& src)
noexcept(std::is_nothrow_copy_constructible<json_base_class_t>::value)
: json_base_class_t(src) : json_base_class_t(src)
#if JSON_DIAGNOSTIC_POSITIONS #if JSON_DIAGNOSTIC_POSITIONS
, start_position(src.start_position) , start_position(src.start_position)
@@ -1442,7 +1443,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
be destroyed. be destroyed.
*/ */
template<typename BasicJsonType> template<typename BasicJsonType>
void convert_iteratively(const BasicJsonType& val) void convert_iteratively(const BasicJsonType& val, std::true_type /*unused*/)
{ {
using other_const_iterator = typename BasicJsonType::const_iterator; using other_const_iterator = typename BasicJsonType::const_iterator;
@@ -1536,21 +1537,38 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_LIKELY(guard.okay())) if (JSON_HEDLEY_LIKELY(guard.okay()))
{ {
// every element comes back to the converting constructor convert_by_serializers(val);
if (val.is_object())
{
using other_object_t = typename BasicJsonType::object_t;
JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
}
else
{
using other_array_t = typename BasicJsonType::array_t;
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
}
return; return;
} }
convert_iteratively(val); // the iterative conversion needs to construct this object type's keys
// from those of @a val; if it cannot, neither can the range constructor,
// and the serializers convert @a val some other way (see #3425)
convert_iteratively(val, std::is_constructible<typename object_t::key_type, const typename BasicJsonType::string_t&> {});
}
/// @brief convert the object or array @a val with the serializers; every
/// element comes back to the converting constructor
template<typename BasicJsonType>
void convert_by_serializers(const BasicJsonType& val)
{
if (val.is_object())
{
using other_object_t = typename BasicJsonType::object_t;
JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
}
else
{
using other_array_t = typename BasicJsonType::array_t;
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
}
}
/// @brief convert @a val whose keys cannot be converted, see @ref convert_structured
template<typename BasicJsonType>
void convert_iteratively(const BasicJsonType& val, std::false_type /*unused*/)
{
convert_by_serializers(val);
} }
@@ -1624,15 +1642,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
static compare_result compare_leaves(const_reference lhs, const_reference rhs, std::true_type /*ordered*/) noexcept static compare_result compare_leaves(const_reference lhs, const_reference rhs, std::true_type /*ordered*/) noexcept
{ {
const std::partial_ordering order = lhs <=> rhs; // *NOPAD* const std::partial_ordering order = lhs <=> rhs; // *NOPAD*
if (order == 0) if (std::is_eq(order))
{ {
return compare_result::equal; return compare_result::equal;
} }
if (order < 0) if (std::is_lt(order))
{ {
return compare_result::less; return compare_result::less;
} }
if (order > 0) if (std::is_gt(order))
{ {
return compare_result::greater; return compare_result::greater;
} }
@@ -3470,30 +3488,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::is_basic_json<BasicJsonType>::value detail::is_basic_json<BasicJsonType>::value
&& detail::is_getable<basic_json_t, ValueType>::value && detail::is_getable<basic_json_t, ValueType>::value
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
#if JSON_DELETE_DEPRECATED_FUNCTIONS
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
{ {
return value(ptr.convert(), default_value); return value(ptr.convert(), default_value);
} }
#endif
template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type, template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
detail::enable_if_t < detail::enable_if_t <
detail::is_basic_json<BasicJsonType>::value detail::is_basic_json<BasicJsonType>::value
&& detail::is_getable<basic_json_t, ReturnType>::value && detail::is_getable<basic_json_t, ReturnType>::value
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
#if JSON_DELETE_DEPRECATED_FUNCTIONS
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
{ {
return value(ptr.convert(), std::forward<ValueType>(default_value)); return value(ptr.convert(), std::forward<ValueType>(default_value));
} }
#endif
/// @brief access the first element /// @brief access the first element
/// @sa https://json.nlohmann.me/api/basic_json/front/ /// @sa https://json.nlohmann.me/api/basic_json/front/
@@ -3849,15 +3859,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{ {
return ptr.contains(this); return ptr.contains(this);
} }
#endif
/// @} /// @}
@@ -3966,30 +3972,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @deprecated This function is deprecated since 3.1.0 and will be removed in /// @deprecated This function is deprecated since 3.1.0 and will be removed in
/// version 4.0.0 of the library. Please use @ref items() instead; /// version 4.0.0 of the library. Please use @ref items() instead;
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`. /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
{ {
return ref.items(); return ref.items();
} }
#endif
/// @brief wrapper to access iterator member functions in range-based for /// @brief wrapper to access iterator member functions in range-based for
/// @sa https://json.nlohmann.me/api/basic_json/items/ /// @sa https://json.nlohmann.me/api/basic_json/items/
/// @deprecated This function is deprecated since 3.1.0 and will be removed in /// @deprecated This function is deprecated since 3.1.0 and will be removed in
/// version 4.0.0 of the library. Please use @ref items() instead; /// version 4.0.0 of the library. Please use @ref items() instead;
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`. /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
{ {
return ref.items(); return ref.items();
} }
#endif
/// @brief helper to access iterator member functions in range-based for /// @brief helper to access iterator member functions in range-based for
/// @sa https://json.nlohmann.me/api/basic_json/items/ /// @sa https://json.nlohmann.me/api/basic_json/items/
@@ -5078,7 +5076,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/ /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
template<typename ScalarType> template<typename ScalarType>
requires std::is_scalar_v<ScalarType> requires std::is_scalar_v<ScalarType>
friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept(std::is_nothrow_constructible<basic_json, ScalarType>::value)
{ {
return basic_json(lhs) <= rhs; return basic_json(lhs) <= rhs;
} }
@@ -5087,7 +5085,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
template<typename ScalarType> template<typename ScalarType>
requires std::is_scalar_v<ScalarType> requires std::is_scalar_v<ScalarType>
friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept(std::is_nothrow_constructible<basic_json, ScalarType>::value)
{ {
return basic_json(lhs) >= rhs; return basic_json(lhs) >= rhs;
} }
@@ -5305,15 +5303,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// version 4.0.0 of the library. Please use /// version 4.0.0 of the library. Please use
/// operator<<(std::ostream&, const basic_json&) instead; that is, /// operator<<(std::ostream&, const basic_json&) instead; that is,
/// replace calls like `j >> o;` with `o << j;`. /// replace calls like `j >> o;` with `o << j;`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
friend std::ostream& operator>>(const basic_json& j, std::ostream& o) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
friend std::ostream& operator>>(const basic_json& j, std::ostream& o) friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
{ {
return o << j; return o << j;
} }
#endif
#endif // JSON_NO_IO #endif // JSON_NO_IO
/// @} /// @}
@@ -5359,13 +5353,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json parse(detail::span_input_adapter&& i,
parser_callback_t cb = nullptr,
const bool allow_exceptions = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
static basic_json parse(detail::span_input_adapter&& i, static basic_json parse(detail::span_input_adapter&& i,
parser_callback_t cb = nullptr, parser_callback_t cb = nullptr,
@@ -5378,7 +5365,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
p.parse(true, result); p.parse(true, result);
return result; return result;
} }
#endif
/// @brief check if the input is valid JSON /// @brief check if the input is valid JSON
/// @sa https://json.nlohmann.me/api/basic_json/accept/ /// @sa https://json.nlohmann.me/api/basic_json/accept/
@@ -5404,11 +5390,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static bool accept(detail::span_input_adapter&& i,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
static bool accept(detail::span_input_adapter&& i, static bool accept(detail::span_input_adapter&& i,
const bool ignore_comments = false, const bool ignore_comments = false,
@@ -5416,7 +5397,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true); return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
} }
#endif
/// @brief generate SAX events /// @brief generate SAX events
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
@@ -5470,14 +5450,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#pragma clang diagnostic ignored "-Wdocumentation-deprecated-sync" #pragma clang diagnostic ignored "-Wdocumentation-deprecated-sync"
#endif #endif
template <typename SAX> template <typename SAX>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
JSON_HEDLEY_NON_NULL(2)
static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
input_format_t format = input_format_t::json,
const bool strict = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
JSON_HEDLEY_NON_NULL(2) JSON_HEDLEY_NON_NULL(2)
static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
@@ -5493,7 +5465,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(sax, strict); : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(sax, strict);
} }
#endif
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
@@ -5504,15 +5475,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// version 4.0.0 of the library. Please use /// version 4.0.0 of the library. Please use
/// operator>>(std::istream&, basic_json&) instead; that is, /// operator>>(std::istream&, basic_json&) instead; that is,
/// replace calls like `j << i;` with `i >> j;`. /// replace calls like `j << i;` with `i >> j;`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
friend std::istream& operator<<(basic_json& j, std::istream& i) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
friend std::istream& operator<<(basic_json& j, std::istream& i) friend std::istream& operator<<(basic_json& j, std::istream& i)
{ {
return operator>>(i, j); return operator>>(i, j);
} }
#endif
/// @brief deserialize from stream /// @brief deserialize from stream
/// @sa https://json.nlohmann.me/api/operator_gtgt/ /// @sa https://json.nlohmann.me/api/operator_gtgt/
@@ -5855,12 +5822,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_cbor(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(const T* ptr, std::size_t len, static basic_json from_cbor(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -5869,15 +5830,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_cbor(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(detail::span_input_adapter&& i, static basic_json from_cbor(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -5886,7 +5840,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, error_handler_t::keep, tag_handler); return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, error_handler_t::keep, tag_handler);
} }
#endif
/// @brief create a JSON value from an input in MessagePack format /// @brief create a JSON value from an input in MessagePack format
/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
@@ -5915,11 +5868,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_msgpack(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
static basic_json from_msgpack(const T* ptr, std::size_t len, static basic_json from_msgpack(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -5927,14 +5875,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_msgpack(ptr, ptr + len, strict, allow_exceptions); return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_msgpack(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
static basic_json from_msgpack(detail::span_input_adapter&& i, static basic_json from_msgpack(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -5942,7 +5884,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::msgpack, strict, allow_exceptions); return from_binary_impl(i.get(), input_format_t::msgpack, strict, allow_exceptions);
} }
#endif
/// @brief create a JSON value from an input in UBJSON format /// @brief create a JSON value from an input in UBJSON format
/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
@@ -5971,11 +5912,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_ubjson(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
static basic_json from_ubjson(const T* ptr, std::size_t len, static basic_json from_ubjson(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -5983,14 +5919,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_ubjson(ptr, ptr + len, strict, allow_exceptions); return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_ubjson(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
static basic_json from_ubjson(detail::span_input_adapter&& i, static basic_json from_ubjson(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -5998,7 +5928,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::ubjson, strict, allow_exceptions); return from_binary_impl(i.get(), input_format_t::ubjson, strict, allow_exceptions);
} }
#endif
/// @brief create a JSON value from an input in BJData format /// @brief create a JSON value from an input in BJData format
/// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
@@ -6025,22 +5954,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions, error_handler); return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions, error_handler);
} }
template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bjdata(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bjdata(ptr, ptr + len))
static basic_json from_bjdata(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true)
{
return from_bjdata(ptr, ptr + len, strict, allow_exceptions);
}
#endif
/// @brief create a JSON value from an input in BON8 format /// @brief create a JSON value from an input in BON8 format
/// @sa https://json.nlohmann.me/api/basic_json/from_bon8/ /// @sa https://json.nlohmann.me/api/basic_json/from_bon8/
template<typename InputType> template<typename InputType>
@@ -6064,22 +5977,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bon8, strict, allow_exceptions); return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bon8, strict, allow_exceptions);
} }
template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bon8(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bon8(ptr, ptr + len))
static basic_json from_bon8(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true)
{
return from_bon8(ptr, ptr + len, strict, allow_exceptions);
}
#endif
/// @brief create a JSON value from an input in BSON format /// @brief create a JSON value from an input in BSON format
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/ /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
template<typename InputType> template<typename InputType>
@@ -6107,11 +6004,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bson(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
static basic_json from_bson(const T* ptr, std::size_t len, static basic_json from_bson(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -6119,14 +6011,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_bson(ptr, ptr + len, strict, allow_exceptions); return from_bson(ptr, ptr + len, strict, allow_exceptions);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bson(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
static basic_json from_bson(detail::span_input_adapter&& i, static basic_json from_bson(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -6134,7 +6020,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::bson, strict, allow_exceptions); return from_binary_impl(i.get(), input_format_t::bson, strict, allow_exceptions);
} }
#endif
/// @} /// @}
////////////////////////// //////////////////////////
@@ -6152,15 +6037,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{ {
return ptr.get_unchecked(this); return ptr.get_unchecked(this);
} }
#endif
/// @brief access specified element via JSON Pointer /// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
@@ -6170,15 +6051,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{ {
return ptr.get_unchecked(this); return ptr.get_unchecked(this);
} }
#endif
/// @brief access specified element via JSON Pointer /// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/ /// @sa https://json.nlohmann.me/api/basic_json/at/
@@ -6188,15 +6065,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{ {
return ptr.get_checked(this); return ptr.get_checked(this);
} }
#endif
/// @brief access specified element via JSON Pointer /// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/ /// @sa https://json.nlohmann.me/api/basic_json/at/
@@ -6206,15 +6079,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{ {
return ptr.get_checked(this); return ptr.get_checked(this);
} }
#endif
/// @brief return flattened JSON value /// @brief return flattened JSON value
/// @sa https://json.nlohmann.me/api/basic_json/flatten/ /// @sa https://json.nlohmann.me/api/basic_json/flatten/
+2 -2
View File
@@ -12,7 +12,7 @@
#include <functional> // equal_to, less #include <functional> // equal_to, less
#include <initializer_list> // initializer_list #include <initializer_list> // initializer_list
#include <iterator> // input_iterator_tag, iterator_traits #include <iterator> // input_iterator_tag, iterator_traits
#include <memory> // allocator #include <memory> // allocator // IWYU pragma: keep
#include <new> // for operator new (placement new) #include <new> // for operator new (placement new)
#include <stdexcept> // for out_of_range #include <stdexcept> // for out_of_range
#include <tuple> // forward_as_tuple #include <tuple> // forward_as_tuple
@@ -78,7 +78,7 @@ private:
/// @brief find the entry for @a key, for either constness of @a self /// @brief find the entry for @a key, for either constness of @a self
/// @note the single place that performs the linear key search /// @note the single place that performs the linear key search
template<typename Self, typename KeyType> template<typename Self, typename KeyType>
static auto find_impl(Self& self, KeyType&& key) -> decltype(self.begin()) static auto find_impl(Self& self, const KeyType& key) -> decltype(self.begin())
{ {
for (auto it = self.begin(); it != self.end(); ++it) for (auto it = self.begin(); it != self.end(); ++it)
{ {
+3840
View File
File diff suppressed because it is too large Load Diff
+56 -208
View File
@@ -3214,10 +3214,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP
#define JSON_DISABLE_ENUM_SERIALIZATION 0 #define JSON_DISABLE_ENUM_SERIALIZATION 0
#endif #endif
#ifndef JSON_DELETE_DEPRECATED_FUNCTIONS
#define JSON_DELETE_DEPRECATED_FUNCTIONS 0
#endif
#ifndef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION #ifndef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 0 #define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 0
#endif #endif
@@ -13700,15 +13696,15 @@ class binary_reader
@param[in] adapter input adapter to read from @param[in] adapter input adapter to read from
@param[in] format the binary format to parse @param[in] format the binary format to parse
@param[in] error_handler how to treat text strings and object keys that @param[in] error_handler_ how to treat text strings and object keys that
are not well-formed UTF-8; none of the supported formats are not well-formed UTF-8; none of the supported formats
requires a decoder to reject those, so the default is to requires a decoder to reject those, so the default is to
@ref error_handler_t::keep them unchanged, as every binary @ref error_handler_t::keep them unchanged, as every binary
reader did before this parameter existed reader did before this parameter existed
*/ */
explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json, explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json,
const error_handler_t error_handler = error_handler_t::keep) noexcept const error_handler_t error_handler_ = error_handler_t::keep) noexcept
: ia(std::move(adapter)), input_format(format), error_handler(error_handler) : ia(std::move(adapter)), input_format(format), error_handler(error_handler_)
{ {
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
} }
@@ -19759,15 +19755,11 @@ class json_pointer
/// @brief return a string representation of the JSON pointer /// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string_t/ /// @sa https://json.nlohmann.me/api/json_pointer/operator_string_t/
#if JSON_DELETE_DEPRECATED_FUNCTIONS
operator string_t() const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
operator string_t() const operator string_t() const
{ {
return to_string(); return to_string();
} }
#endif
#ifndef JSON_NO_IO #ifndef JSON_NO_IO
/// @brief write string representation of the JSON pointer to stream /// @brief write string representation of the JSON pointer to stream
@@ -20006,6 +19998,8 @@ class json_pointer
typename BasicJsonType::size_type idx{}; typename BasicJsonType::size_type idx{};
switch (parse_array_index<BasicJsonType>(s, idx)) switch (parse_array_index<BasicJsonType>(s, idx))
{ {
// the branches differ in their messages, not after JSON_THROW's expansion
// NOLINTNEXTLINE(bugprone-branch-clone)
case array_index_status::leading_zero: case array_index_status::leading_zero:
JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
case array_index_status::not_a_number: case array_index_status::not_a_number:
@@ -20369,6 +20363,8 @@ class json_pointer
typename BasicJsonType::size_type idx{}; typename BasicJsonType::size_type idx{};
switch (parse_array_index<BasicJsonType>(reference_token, idx)) switch (parse_array_index<BasicJsonType>(reference_token, idx))
{ {
// the branches differ in their messages, not after JSON_THROW's expansion
// NOLINTNEXTLINE(bugprone-branch-clone)
case array_index_status::leading_zero: case array_index_status::leading_zero:
JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", reference_token, "' must not begin with '0'"), nullptr)); JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", reference_token, "' must not begin with '0'"), nullptr));
case array_index_status::not_a_number: case array_index_status::not_a_number:
@@ -20700,15 +20696,11 @@ class json_pointer
/// @brief compares JSON pointer and string for equality /// @brief compares JSON pointer and string for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
#if JSON_DELETE_DEPRECATED_FUNCTIONS
bool operator==(const string_t& rhs) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
bool operator==(const string_t& rhs) const bool operator==(const string_t& rhs) const
{ {
return *this == json_pointer(rhs); return *this == json_pointer(rhs);
} }
#endif
/// @brief 3-way compares two JSON pointers /// @brief 3-way compares two JSON pointers
template<typename RefStringTypeRhs> template<typename RefStringTypeRhs>
@@ -20783,31 +20775,21 @@ inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
template<typename RefStringTypeLhs, template<typename RefStringTypeLhs,
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) const StringType& rhs)
{ {
return lhs == json_pointer<RefStringTypeLhs>(rhs); return lhs == json_pointer<RefStringTypeLhs>(rhs);
} }
#endif
template<typename RefStringTypeRhs, template<typename RefStringTypeRhs,
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator==(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
inline bool operator==(const StringType& lhs, inline bool operator==(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) const json_pointer<RefStringTypeRhs>& rhs)
{ {
return json_pointer<RefStringTypeRhs>(lhs) == rhs; return json_pointer<RefStringTypeRhs>(lhs) == rhs;
} }
#endif
template<typename RefStringTypeLhs, typename RefStringTypeRhs> template<typename RefStringTypeLhs, typename RefStringTypeRhs>
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
@@ -20818,31 +20800,21 @@ inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
template<typename RefStringTypeLhs, template<typename RefStringTypeLhs,
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs) const StringType& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
#endif
template<typename RefStringTypeRhs, template<typename RefStringTypeRhs,
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
inline bool operator!=(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
inline bool operator!=(const StringType& lhs, inline bool operator!=(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs) const json_pointer<RefStringTypeRhs>& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
#endif
template<typename RefStringTypeLhs, typename RefStringTypeRhs> template<typename RefStringTypeLhs, typename RefStringTypeRhs>
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
@@ -23517,18 +23489,18 @@ class binary_writer
switch (error_handler) switch (error_handler)
{ {
case error_handler_t::keep: case error_handler_t::keep:
return s; return s; // NOLINT(bugprone-return-const-ref-from-parameter): callers pass lvalues that outlive the call
case error_handler_t::strict: case error_handler_t::strict:
check_utf8(s, context); check_utf8(s, context);
return s; return s; // NOLINT(bugprone-return-const-ref-from-parameter): callers pass lvalues that outlive the call
case error_handler_t::replace: case error_handler_t::replace:
case error_handler_t::ignore: case error_handler_t::ignore:
default: default:
if (is_valid_utf8(s)) if (is_valid_utf8(s))
{ {
return s; return s; // NOLINT(bugprone-return-const-ref-from-parameter): callers pass lvalues that outlive the call
} }
storage = sanitize_utf8(s, error_handler); storage = sanitize_utf8(s, error_handler);
return storage; return storage;
@@ -25713,6 +25685,11 @@ class serializer
@a ensure_ascii is a template parameter here so that the branch on it is @a ensure_ascii is a template parameter here so that the branch on it is
resolved once, outside the loop; see @ref dump_escaped. resolved once, outside the loop; see @ref dump_escaped.
*/ */
#ifdef JSON_HEDLEY_MSVC_VERSION
#pragma warning(push)
// EnsureAscii is a template parameter; C++11 has no if constexpr
#pragma warning(disable : 4127) // conditional expression is constant
#endif
template<bool EnsureAscii> template<bool EnsureAscii>
void dump_escaped_impl(const string_t& s) void dump_escaped_impl(const string_t& s)
{ {
@@ -26062,6 +26039,9 @@ class serializer
} }
} }
} }
#ifdef JSON_HEDLEY_MSVC_VERSION
#pragma warning(pop)
#endif
private: private:
/*! /*!
@@ -26644,7 +26624,7 @@ NLOHMANN_JSON_NAMESPACE_END
#include <functional> // equal_to, less #include <functional> // equal_to, less
#include <initializer_list> // initializer_list #include <initializer_list> // initializer_list
#include <iterator> // input_iterator_tag, iterator_traits #include <iterator> // input_iterator_tag, iterator_traits
#include <memory> // allocator #include <memory> // allocator // IWYU pragma: keep
#include <new> // for operator new (placement new) #include <new> // for operator new (placement new)
#include <stdexcept> // for out_of_range #include <stdexcept> // for out_of_range
#include <tuple> // forward_as_tuple #include <tuple> // forward_as_tuple
@@ -26713,7 +26693,7 @@ private:
/// @brief find the entry for @a key, for either constness of @a self /// @brief find the entry for @a key, for either constness of @a self
/// @note the single place that performs the linear key search /// @note the single place that performs the linear key search
template<typename Self, typename KeyType> template<typename Self, typename KeyType>
static auto find_impl(Self& self, KeyType&& key) -> decltype(self.begin()) static auto find_impl(Self& self, const KeyType& key) -> decltype(self.begin())
{ {
for (auto it = self.begin(); it != self.end(); ++it) for (auto it = self.begin(); it != self.end(); ++it)
{ {
@@ -28017,6 +27997,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
never name it to call this constructor itself. never name it to call this constructor itself.
*/ */
basic_json(copy_construct_tag /*unused*/, const basic_json& src) basic_json(copy_construct_tag /*unused*/, const basic_json& src)
noexcept(std::is_nothrow_copy_constructible<json_base_class_t>::value)
: json_base_class_t(src) : json_base_class_t(src)
#if JSON_DIAGNOSTIC_POSITIONS #if JSON_DIAGNOSTIC_POSITIONS
, start_position(src.start_position) , start_position(src.start_position)
@@ -28411,7 +28392,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
be destroyed. be destroyed.
*/ */
template<typename BasicJsonType> template<typename BasicJsonType>
void convert_iteratively(const BasicJsonType& val) void convert_iteratively(const BasicJsonType& val, std::true_type /*unused*/)
{ {
using other_const_iterator = typename BasicJsonType::const_iterator; using other_const_iterator = typename BasicJsonType::const_iterator;
@@ -28505,21 +28486,38 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
if (JSON_HEDLEY_LIKELY(guard.okay())) if (JSON_HEDLEY_LIKELY(guard.okay()))
{ {
// every element comes back to the converting constructor convert_by_serializers(val);
if (val.is_object())
{
using other_object_t = typename BasicJsonType::object_t;
JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
}
else
{
using other_array_t = typename BasicJsonType::array_t;
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
}
return; return;
} }
convert_iteratively(val); // the iterative conversion needs to construct this object type's keys
// from those of @a val; if it cannot, neither can the range constructor,
// and the serializers convert @a val some other way (see #3425)
convert_iteratively(val, std::is_constructible<typename object_t::key_type, const typename BasicJsonType::string_t&> {});
}
/// @brief convert the object or array @a val with the serializers; every
/// element comes back to the converting constructor
template<typename BasicJsonType>
void convert_by_serializers(const BasicJsonType& val)
{
if (val.is_object())
{
using other_object_t = typename BasicJsonType::object_t;
JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
}
else
{
using other_array_t = typename BasicJsonType::array_t;
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
}
}
/// @brief convert @a val whose keys cannot be converted, see @ref convert_structured
template<typename BasicJsonType>
void convert_iteratively(const BasicJsonType& val, std::false_type /*unused*/)
{
convert_by_serializers(val);
} }
@@ -28593,15 +28591,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
static compare_result compare_leaves(const_reference lhs, const_reference rhs, std::true_type /*ordered*/) noexcept static compare_result compare_leaves(const_reference lhs, const_reference rhs, std::true_type /*ordered*/) noexcept
{ {
const std::partial_ordering order = lhs <=> rhs; // *NOPAD* const std::partial_ordering order = lhs <=> rhs; // *NOPAD*
if (order == 0) if (std::is_eq(order))
{ {
return compare_result::equal; return compare_result::equal;
} }
if (order < 0) if (std::is_lt(order))
{ {
return compare_result::less; return compare_result::less;
} }
if (order > 0) if (std::is_gt(order))
{ {
return compare_result::greater; return compare_result::greater;
} }
@@ -30439,30 +30437,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
detail::is_basic_json<BasicJsonType>::value detail::is_basic_json<BasicJsonType>::value
&& detail::is_getable<basic_json_t, ValueType>::value && detail::is_getable<basic_json_t, ValueType>::value
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
#if JSON_DELETE_DEPRECATED_FUNCTIONS
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
{ {
return value(ptr.convert(), default_value); return value(ptr.convert(), default_value);
} }
#endif
template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type, template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
detail::enable_if_t < detail::enable_if_t <
detail::is_basic_json<BasicJsonType>::value detail::is_basic_json<BasicJsonType>::value
&& detail::is_getable<basic_json_t, ReturnType>::value && detail::is_getable<basic_json_t, ReturnType>::value
&& !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
#if JSON_DELETE_DEPRECATED_FUNCTIONS
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
{ {
return value(ptr.convert(), std::forward<ValueType>(default_value)); return value(ptr.convert(), std::forward<ValueType>(default_value));
} }
#endif
/// @brief access the first element /// @brief access the first element
/// @sa https://json.nlohmann.me/api/basic_json/front/ /// @sa https://json.nlohmann.me/api/basic_json/front/
@@ -30818,15 +30808,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{ {
return ptr.contains(this); return ptr.contains(this);
} }
#endif
/// @} /// @}
@@ -30935,30 +30921,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @deprecated This function is deprecated since 3.1.0 and will be removed in /// @deprecated This function is deprecated since 3.1.0 and will be removed in
/// version 4.0.0 of the library. Please use @ref items() instead; /// version 4.0.0 of the library. Please use @ref items() instead;
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`. /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
{ {
return ref.items(); return ref.items();
} }
#endif
/// @brief wrapper to access iterator member functions in range-based for /// @brief wrapper to access iterator member functions in range-based for
/// @sa https://json.nlohmann.me/api/basic_json/items/ /// @sa https://json.nlohmann.me/api/basic_json/items/
/// @deprecated This function is deprecated since 3.1.0 and will be removed in /// @deprecated This function is deprecated since 3.1.0 and will be removed in
/// version 4.0.0 of the library. Please use @ref items() instead; /// version 4.0.0 of the library. Please use @ref items() instead;
/// that is, replace `json::iterator_wrapper(j)` with `j.items()`. /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
{ {
return ref.items(); return ref.items();
} }
#endif
/// @brief helper to access iterator member functions in range-based for /// @brief helper to access iterator member functions in range-based for
/// @sa https://json.nlohmann.me/api/basic_json/items/ /// @sa https://json.nlohmann.me/api/basic_json/items/
@@ -32047,7 +32025,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/ /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
template<typename ScalarType> template<typename ScalarType>
requires std::is_scalar_v<ScalarType> requires std::is_scalar_v<ScalarType>
friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept(std::is_nothrow_constructible<basic_json, ScalarType>::value)
{ {
return basic_json(lhs) <= rhs; return basic_json(lhs) <= rhs;
} }
@@ -32056,7 +32034,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
template<typename ScalarType> template<typename ScalarType>
requires std::is_scalar_v<ScalarType> requires std::is_scalar_v<ScalarType>
friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept(std::is_nothrow_constructible<basic_json, ScalarType>::value)
{ {
return basic_json(lhs) >= rhs; return basic_json(lhs) >= rhs;
} }
@@ -32274,15 +32252,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// version 4.0.0 of the library. Please use /// version 4.0.0 of the library. Please use
/// operator<<(std::ostream&, const basic_json&) instead; that is, /// operator<<(std::ostream&, const basic_json&) instead; that is,
/// replace calls like `j >> o;` with `o << j;`. /// replace calls like `j >> o;` with `o << j;`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
friend std::ostream& operator>>(const basic_json& j, std::ostream& o) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
friend std::ostream& operator>>(const basic_json& j, std::ostream& o) friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
{ {
return o << j; return o << j;
} }
#endif
#endif // JSON_NO_IO #endif // JSON_NO_IO
/// @} /// @}
@@ -32328,13 +32302,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json parse(detail::span_input_adapter&& i,
parser_callback_t cb = nullptr,
const bool allow_exceptions = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
static basic_json parse(detail::span_input_adapter&& i, static basic_json parse(detail::span_input_adapter&& i,
parser_callback_t cb = nullptr, parser_callback_t cb = nullptr,
@@ -32347,7 +32314,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
p.parse(true, result); p.parse(true, result);
return result; return result;
} }
#endif
/// @brief check if the input is valid JSON /// @brief check if the input is valid JSON
/// @sa https://json.nlohmann.me/api/basic_json/accept/ /// @sa https://json.nlohmann.me/api/basic_json/accept/
@@ -32373,11 +32339,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static bool accept(detail::span_input_adapter&& i,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
static bool accept(detail::span_input_adapter&& i, static bool accept(detail::span_input_adapter&& i,
const bool ignore_comments = false, const bool ignore_comments = false,
@@ -32385,7 +32346,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true); return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas, true).accept(true);
} }
#endif
/// @brief generate SAX events /// @brief generate SAX events
/// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
@@ -32439,14 +32399,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#pragma clang diagnostic ignored "-Wdocumentation-deprecated-sync" #pragma clang diagnostic ignored "-Wdocumentation-deprecated-sync"
#endif #endif
template <typename SAX> template <typename SAX>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
JSON_HEDLEY_NON_NULL(2)
static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
input_format_t format = input_format_t::json,
const bool strict = true,
const bool ignore_comments = false,
const bool ignore_trailing_commas = false) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
JSON_HEDLEY_NON_NULL(2) JSON_HEDLEY_NON_NULL(2)
static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
@@ -32462,7 +32414,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
: detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(sax, strict); : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(sax, strict);
} }
#endif
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
@@ -32473,15 +32424,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// version 4.0.0 of the library. Please use /// version 4.0.0 of the library. Please use
/// operator>>(std::istream&, basic_json&) instead; that is, /// operator>>(std::istream&, basic_json&) instead; that is,
/// replace calls like `j << i;` with `i >> j;`. /// replace calls like `j << i;` with `i >> j;`.
#if JSON_DELETE_DEPRECATED_FUNCTIONS
friend std::istream& operator<<(basic_json& j, std::istream& i) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
friend std::istream& operator<<(basic_json& j, std::istream& i) friend std::istream& operator<<(basic_json& j, std::istream& i)
{ {
return operator>>(i, j); return operator>>(i, j);
} }
#endif
/// @brief deserialize from stream /// @brief deserialize from stream
/// @sa https://json.nlohmann.me/api/operator_gtgt/ /// @sa https://json.nlohmann.me/api/operator_gtgt/
@@ -32824,12 +32771,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_cbor(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(const T* ptr, std::size_t len, static basic_json from_cbor(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -32838,15 +32779,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_cbor(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(detail::span_input_adapter&& i, static basic_json from_cbor(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -32855,7 +32789,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, error_handler_t::keep, tag_handler); return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, error_handler_t::keep, tag_handler);
} }
#endif
/// @brief create a JSON value from an input in MessagePack format /// @brief create a JSON value from an input in MessagePack format
/// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
@@ -32884,11 +32817,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_msgpack(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
static basic_json from_msgpack(const T* ptr, std::size_t len, static basic_json from_msgpack(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -32896,14 +32824,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_msgpack(ptr, ptr + len, strict, allow_exceptions); return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_msgpack(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
static basic_json from_msgpack(detail::span_input_adapter&& i, static basic_json from_msgpack(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -32911,7 +32833,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::msgpack, strict, allow_exceptions); return from_binary_impl(i.get(), input_format_t::msgpack, strict, allow_exceptions);
} }
#endif
/// @brief create a JSON value from an input in UBJSON format /// @brief create a JSON value from an input in UBJSON format
/// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
@@ -32940,11 +32861,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_ubjson(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
static basic_json from_ubjson(const T* ptr, std::size_t len, static basic_json from_ubjson(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -32952,14 +32868,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_ubjson(ptr, ptr + len, strict, allow_exceptions); return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_ubjson(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
static basic_json from_ubjson(detail::span_input_adapter&& i, static basic_json from_ubjson(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -32967,7 +32877,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::ubjson, strict, allow_exceptions); return from_binary_impl(i.get(), input_format_t::ubjson, strict, allow_exceptions);
} }
#endif
/// @brief create a JSON value from an input in BJData format /// @brief create a JSON value from an input in BJData format
/// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
@@ -32994,22 +32903,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions, error_handler); return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions, error_handler);
} }
template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bjdata(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bjdata(ptr, ptr + len))
static basic_json from_bjdata(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true)
{
return from_bjdata(ptr, ptr + len, strict, allow_exceptions);
}
#endif
/// @brief create a JSON value from an input in BON8 format /// @brief create a JSON value from an input in BON8 format
/// @sa https://json.nlohmann.me/api/basic_json/from_bon8/ /// @sa https://json.nlohmann.me/api/basic_json/from_bon8/
template<typename InputType> template<typename InputType>
@@ -33033,22 +32926,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bon8, strict, allow_exceptions); return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bon8, strict, allow_exceptions);
} }
template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bon8(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.13.0, from_bon8(ptr, ptr + len))
static basic_json from_bon8(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true)
{
return from_bon8(ptr, ptr + len, strict, allow_exceptions);
}
#endif
/// @brief create a JSON value from an input in BSON format /// @brief create a JSON value from an input in BSON format
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/ /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
template<typename InputType> template<typename InputType>
@@ -33076,11 +32953,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template<typename T> template<typename T>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bson(const T* ptr, std::size_t len,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
static basic_json from_bson(const T* ptr, std::size_t len, static basic_json from_bson(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
@@ -33088,14 +32960,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_bson(ptr, ptr + len, strict, allow_exceptions); return from_bson(ptr, ptr + len, strict, allow_exceptions);
} }
#endif
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
#if JSON_DELETE_DEPRECATED_FUNCTIONS
static basic_json from_bson(detail::span_input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
static basic_json from_bson(detail::span_input_adapter&& i, static basic_json from_bson(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
@@ -33103,7 +32969,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{ {
return from_binary_impl(i.get(), input_format_t::bson, strict, allow_exceptions); return from_binary_impl(i.get(), input_format_t::bson, strict, allow_exceptions);
} }
#endif
/// @} /// @}
////////////////////////// //////////////////////////
@@ -33121,15 +32986,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{ {
return ptr.get_unchecked(this); return ptr.get_unchecked(this);
} }
#endif
/// @brief access specified element via JSON Pointer /// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
@@ -33139,15 +33000,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{ {
return ptr.get_unchecked(this); return ptr.get_unchecked(this);
} }
#endif
/// @brief access specified element via JSON Pointer /// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/ /// @sa https://json.nlohmann.me/api/basic_json/at/
@@ -33157,15 +33014,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
{ {
return ptr.get_checked(this); return ptr.get_checked(this);
} }
#endif
/// @brief access specified element via JSON Pointer /// @brief access specified element via JSON Pointer
/// @sa https://json.nlohmann.me/api/basic_json/at/ /// @sa https://json.nlohmann.me/api/basic_json/at/
@@ -33175,15 +33028,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
} }
template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
#if JSON_DELETE_DEPRECATED_FUNCTIONS
const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const = delete;
#else
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
{ {
return ptr.get_checked(this); return ptr.get_checked(this);
} }
#endif
/// @brief return flattened JSON value /// @brief return flattened JSON value
/// @sa https://json.nlohmann.me/api/basic_json/flatten/ /// @sa https://json.nlohmann.me/api/basic_json/flatten/
@@ -34343,7 +34192,6 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
#undef JSON_PRECISE_STREAM_POSITION #undef JSON_PRECISE_STREAM_POSITION
#undef JSON_STRICT_NUL_HANDLING #undef JSON_STRICT_NUL_HANDLING
#undef JSON_STRICT_BINARY_UTF8 #undef JSON_STRICT_BINARY_UTF8
#undef JSON_DELETE_DEPRECATED_FUNCTIONS
#endif #endif
// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
+2 -1
View File
@@ -10,7 +10,8 @@
#include <cstdint> // uint8_t #include <cstdint> // uint8_t
#include <cstddef> // size_t #include <cstddef> // size_t
#include <fstream> // ifstream, istreambuf_iterator, ios #include <fstream> // ifstream, ios
#include <iterator> // istream_iterator
#include <vector> // vector #include <vector> // vector
namespace utils namespace utils
+1 -1
View File
@@ -567,7 +567,7 @@ struct allocator_no_forward : std::allocator<T>
{ {
allocator_no_forward() = default; allocator_no_forward() = default;
template <class U> template <class U>
allocator_no_forward(allocator_no_forward<U> /*unused*/) {} allocator_no_forward(const allocator_no_forward<U>& /*unused*/) {}
template <class U> template <class U>
struct rebind struct rebind
+65 -55
View File
@@ -7,6 +7,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
#include "test_utils.hpp"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -25,18 +26,27 @@ struct ill_formed_case
// RFC 3629 ill-formed sequences used throughout this file, plus one // RFC 3629 ill-formed sequences used throughout this file, plus one
// well-formed sequence for contrast // well-formed sequence for contrast
const std::vector<ill_formed_case> ill_formed_cases = std::vector<ill_formed_case> ill_formed_cases()
{ {
{"overlong", "\xC0\xAE"}, return
{"lone_0xFF", "\xFF"}, {
{"truncated", "\xE2\x82"}, {"overlong", "\xC0\xAE"},
{"surrogate", "\xED\xA0\x80"}, {"lone_0xFF", "\xFF"},
}; {"truncated", "\xE2\x82"},
{"surrogate", "\xED\xA0\x80"},
};
}
const std::string valid_sequence = "\xC3\xA9"; // U+00E9, "é" std::string valid_sequence()
{
return "\xC3\xA9"; // U+00E9, "é"
}
using eh = json::error_handler_t; using eh = json::error_handler_t;
const std::vector<eh> all_handlers = {eh::strict, eh::replace, eh::ignore, eh::keep}; std::vector<eh> all_handlers()
{
return {eh::strict, eh::replace, eh::ignore, eh::keep};
}
// what dump()+parse() produces for a sanitizing error_handler; this is the // what dump()+parse() produces for a sanitizing error_handler; this is the
// ground truth every binary writer/reader is checked against // ground truth every binary writer/reader is checked against
@@ -51,9 +61,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
{ {
SECTION("writers: string value") SECTION("writers: string value")
{ {
for (const auto& c : ill_formed_cases) for (const auto& c : ill_formed_cases())
{ {
CAPTURE(c.name); CAPTURE(c.name)
const json jval = c.bytes; const json jval = c.bytes;
CHECK_THROWS_AS(json::to_cbor(jval, eh::strict), json::type_error&); CHECK_THROWS_AS(json::to_cbor(jval, eh::strict), json::type_error&);
@@ -71,7 +81,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
eh::replace, eh::ignore eh::replace, eh::ignore
}) })
{ {
CAPTURE(static_cast<int>(h)); CAPTURE(static_cast<int>(h))
const std::string expected = dump_and_parse(c.bytes, h); const std::string expected = dump_and_parse(c.bytes, h);
CHECK(json::from_cbor(json::to_cbor(jval, h)).get<std::string>() == expected); CHECK(json::from_cbor(json::to_cbor(jval, h)).get<std::string>() == expected);
@@ -103,9 +113,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
SECTION("writers: object key") SECTION("writers: object key")
{ {
for (const auto& c : ill_formed_cases) for (const auto& c : ill_formed_cases())
{ {
CAPTURE(c.name); CAPTURE(c.name)
json jobj; json jobj;
jobj[c.bytes] = 1; jobj[c.bytes] = 1;
@@ -120,7 +130,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
eh::replace, eh::ignore eh::replace, eh::ignore
}) })
{ {
CAPTURE(static_cast<int>(h)); CAPTURE(static_cast<int>(h))
const std::string expected = dump_and_parse(c.bytes, h); const std::string expected = dump_and_parse(c.bytes, h);
CHECK(json::from_cbor(json::to_cbor(jobj, h)).begin().key() == expected); CHECK(json::from_cbor(json::to_cbor(jobj, h)).begin().key() == expected);
@@ -141,9 +151,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
SECTION("readers: string value") SECTION("readers: string value")
{ {
for (const auto& c : ill_formed_cases) for (const auto& c : ill_formed_cases())
{ {
CAPTURE(c.name); CAPTURE(c.name)
// bytes produced the lenient (keep) way, as any binary reader // bytes produced the lenient (keep) way, as any binary reader
// accepted them before this parameter existed // accepted them before this parameter existed
@@ -166,15 +176,15 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == c.bytes); CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == c.bytes);
// strict: parse_error.113, discarded (not thrown) when allow_exceptions is false // strict: parse_error.113, discarded (not thrown) when allow_exceptions is false
CHECK_THROWS_AS(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict)), json::parse_error&);
CHECK(json::from_cbor(cbor_bytes, true, false, json::cbor_tag_handler_t::error, eh::strict).is_discarded()); CHECK(json::from_cbor(cbor_bytes, true, false, json::cbor_tag_handler_t::error, eh::strict).is_discarded());
CHECK_THROWS_AS(json::from_msgpack(msgpack_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_msgpack(msgpack_bytes, true, true, eh::strict)), json::parse_error&);
CHECK(json::from_msgpack(msgpack_bytes, true, false, eh::strict).is_discarded()); CHECK(json::from_msgpack(msgpack_bytes, true, false, eh::strict).is_discarded());
CHECK_THROWS_AS(json::from_ubjson(ubjson_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_ubjson(ubjson_bytes, true, true, eh::strict)), json::parse_error&);
CHECK(json::from_ubjson(ubjson_bytes, true, false, eh::strict).is_discarded()); CHECK(json::from_ubjson(ubjson_bytes, true, false, eh::strict).is_discarded());
CHECK_THROWS_AS(json::from_bjdata(bjdata_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_bjdata(bjdata_bytes, true, true, eh::strict)), json::parse_error&);
CHECK(json::from_bjdata(bjdata_bytes, true, false, eh::strict).is_discarded()); CHECK(json::from_bjdata(bjdata_bytes, true, false, eh::strict).is_discarded());
CHECK_THROWS_AS(json::from_bson(bson_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_bson(bson_bytes, true, true, eh::strict)), json::parse_error&);
CHECK(json::from_bson(bson_bytes, true, false, eh::strict).is_discarded()); CHECK(json::from_bson(bson_bytes, true, false, eh::strict).is_discarded());
// replace / ignore: match what dump() would have sanitized the same bytes to // replace / ignore: match what dump() would have sanitized the same bytes to
@@ -183,7 +193,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
eh::replace, eh::ignore eh::replace, eh::ignore
}) })
{ {
CAPTURE(static_cast<int>(h)); CAPTURE(static_cast<int>(h))
const std::string expected = dump_and_parse(c.bytes, h); const std::string expected = dump_and_parse(c.bytes, h);
CHECK(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, h).get<std::string>() == expected); CHECK(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, h).get<std::string>() == expected);
@@ -197,9 +207,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
SECTION("readers: object key") SECTION("readers: object key")
{ {
for (const auto& c : ill_formed_cases) for (const auto& c : ill_formed_cases())
{ {
CAPTURE(c.name); CAPTURE(c.name)
json jobj; json jobj;
jobj[c.bytes] = 1; jobj[c.bytes] = 1;
@@ -215,18 +225,18 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
CHECK(json::from_bjdata(bjdata_bytes).begin().key() == c.bytes); CHECK(json::from_bjdata(bjdata_bytes).begin().key() == c.bytes);
CHECK(json::from_bson(bson_bytes).begin().key() == c.bytes); CHECK(json::from_bson(bson_bytes).begin().key() == c.bytes);
CHECK_THROWS_AS(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict)), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(msgpack_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_msgpack(msgpack_bytes, true, true, eh::strict)), json::parse_error&);
CHECK_THROWS_AS(json::from_ubjson(ubjson_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_ubjson(ubjson_bytes, true, true, eh::strict)), json::parse_error&);
CHECK_THROWS_AS(json::from_bjdata(bjdata_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_bjdata(bjdata_bytes, true, true, eh::strict)), json::parse_error&);
CHECK_THROWS_AS(json::from_bson(bson_bytes, true, true, eh::strict), json::parse_error&); CHECK_THROWS_AS(utils::ignore_return_value(json::from_bson(bson_bytes, true, true, eh::strict)), json::parse_error&);
for (const auto h : for (const auto h :
{ {
eh::replace, eh::ignore eh::replace, eh::ignore
}) })
{ {
CAPTURE(static_cast<int>(h)); CAPTURE(static_cast<int>(h))
const std::string expected = dump_and_parse(c.bytes, h); const std::string expected = dump_and_parse(c.bytes, h);
CHECK(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, h).begin().key() == expected); CHECK(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, h).begin().key() == expected);
@@ -240,30 +250,30 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
SECTION("well-formed UTF-8 is unaffected by error_handler") SECTION("well-formed UTF-8 is unaffected by error_handler")
{ {
const json jval = valid_sequence; const json jval = valid_sequence();
json jobj; json jobj;
jobj[valid_sequence] = valid_sequence; jobj[valid_sequence()] = valid_sequence();
for (const auto h : all_handlers) for (const auto h : all_handlers())
{ {
CAPTURE(static_cast<int>(h)); CAPTURE(static_cast<int>(h))
CHECK(json::from_cbor(json::to_cbor(jval, h)).get<std::string>() == valid_sequence); CHECK(json::from_cbor(json::to_cbor(jval, h)).get<std::string>() == valid_sequence());
CHECK(json::from_msgpack(json::to_msgpack(jval, h)).get<std::string>() == valid_sequence); CHECK(json::from_msgpack(json::to_msgpack(jval, h)).get<std::string>() == valid_sequence());
CHECK(json::from_ubjson(json::to_ubjson(jval, false, false, h)).get<std::string>() == valid_sequence); CHECK(json::from_ubjson(json::to_ubjson(jval, false, false, h)).get<std::string>() == valid_sequence());
CHECK(json::from_bjdata(json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, h)).get<std::string>() == valid_sequence); CHECK(json::from_bjdata(json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, h)).get<std::string>() == valid_sequence());
CHECK(json::from_bson(json::to_bson(jobj, h)).begin().key() == valid_sequence); CHECK(json::from_bson(json::to_bson(jobj, h)).begin().key() == valid_sequence());
CHECK(json::from_cbor(json::to_cbor(jval, eh::keep), true, true, json::cbor_tag_handler_t::error, h).get<std::string>() == valid_sequence); CHECK(json::from_cbor(json::to_cbor(jval, eh::keep), true, true, json::cbor_tag_handler_t::error, h).get<std::string>() == valid_sequence());
CHECK(json::from_msgpack(json::to_msgpack(jval), true, true, h).get<std::string>() == valid_sequence); CHECK(json::from_msgpack(json::to_msgpack(jval), true, true, h).get<std::string>() == valid_sequence());
} }
} }
SECTION("dump() with error_handler_t::keep writes raw bytes as is") SECTION("dump() with error_handler_t::keep writes raw bytes as is")
{ {
for (const auto& c : ill_formed_cases) for (const auto& c : ill_formed_cases())
{ {
CAPTURE(c.name); CAPTURE(c.name)
const json jval = c.bytes; const json jval = c.bytes;
const std::string dumped = jval.dump(-1, ' ', false, eh::keep); const std::string dumped = jval.dump(-1, ' ', false, eh::keep);
@@ -276,10 +286,10 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
// well-formed characters around an ill-formed sequence are still // well-formed characters around an ill-formed sequence are still
// escaped as usual under ensure_ascii // escaped as usual under ensure_ascii
const json mixed = valid_sequence + ill_formed_cases[1].bytes; // "é" + lone 0xFF const json mixed = valid_sequence() + ill_formed_cases()[1].bytes; // "é" + lone 0xFF
const std::string dumped_mixed = mixed.dump(-1, ' ', true, eh::keep); const std::string dumped_mixed = mixed.dump(-1, ' ', true, eh::keep);
CHECK(dumped_mixed.find("\\u00e9") != std::string::npos); CHECK(dumped_mixed.find("\\u00e9") != std::string::npos);
CHECK(dumped_mixed.find(ill_formed_cases[1].bytes) != std::string::npos); CHECK(dumped_mixed.find(ill_formed_cases()[1].bytes) != std::string::npos);
// the byte that ends an ill-formed sequence is read again, so a quote, // the byte that ends an ill-formed sequence is read again, so a quote,
// a backslash, or a control character after it is still escaped, and // a backslash, or a control character after it is still escaped, and
@@ -289,7 +299,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
false, true false, true
}) })
{ {
CAPTURE(ensure_ascii); CAPTURE(ensure_ascii)
CHECK(json("\xC3\"").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\\"\""); CHECK(json("\xC3\"").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\\"\"");
CHECK(json("\xC3\\").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\\\\""); CHECK(json("\xC3\\").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\\\\"");
CHECK(json("\xC3\n").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\n\""); CHECK(json("\xC3\n").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\n\"");
@@ -303,12 +313,12 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
SECTION("to_msgpack defaults to keep; to_bon8 is not affected by error_handler") SECTION("to_msgpack defaults to keep; to_bon8 is not affected by error_handler")
{ {
const json jval = ill_formed_cases[1].bytes; // lone 0xFF const json jval = ill_formed_cases()[1].bytes; // lone 0xFF
// to_msgpack's error_handler defaults to keep, as MessagePack's spec // to_msgpack's error_handler defaults to keep, as MessagePack's spec
// allows any bytes in a str, so the bytes are passed through // allows any bytes in a str, so the bytes are passed through
CHECK(json::to_msgpack(jval) == json::to_msgpack(jval, eh::keep)); CHECK(json::to_msgpack(jval) == json::to_msgpack(jval, eh::keep));
CHECK(json::from_msgpack(json::to_msgpack(jval)).get<std::string>() == ill_formed_cases[1].bytes); CHECK(json::from_msgpack(json::to_msgpack(jval)).get<std::string>() == ill_formed_cases()[1].bytes);
// the diagnostics context of an ill-formed key is the object // the diagnostics context of an ill-formed key is the object
json jobj; json jobj;
@@ -322,14 +332,14 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
SECTION("allow_exceptions=false with error_handler_t::strict discards the value") SECTION("allow_exceptions=false with error_handler_t::strict discards the value")
{ {
const auto bytes = json::to_cbor(json(ill_formed_cases[0].bytes), eh::keep); const auto bytes = json::to_cbor(json(ill_formed_cases()[0].bytes), eh::keep);
const json result = json::from_cbor(bytes, true, false, json::cbor_tag_handler_t::error, eh::strict); const json result = json::from_cbor(bytes, true, false, json::cbor_tag_handler_t::error, eh::strict);
CHECK(result.is_discarded()); CHECK(result.is_discarded());
} }
SECTION("default parameters are unchanged") SECTION("default parameters are unchanged")
{ {
const json jval = ill_formed_cases[0].bytes; const json jval = ill_formed_cases()[0].bytes;
// to_*: the default error_handler is keep, so ill-formed bytes are // to_*: the default error_handler is keep, so ill-formed bytes are
// written unchanged, exactly as in release 3.12.0 (it is strict only // written unchanged, exactly as in release 3.12.0 (it is strict only
@@ -347,16 +357,16 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
// from_*: the default error_handler is keep, so ill-formed bytes are // from_*: the default error_handler is keep, so ill-formed bytes are
// still accepted unchanged, exactly as in release 3.12.0 // still accepted unchanged, exactly as in release 3.12.0
const auto cbor_bytes = json::to_cbor(jval, eh::keep); const auto cbor_bytes = json::to_cbor(jval, eh::keep);
CHECK(json::from_cbor(cbor_bytes).get<std::string>() == ill_formed_cases[0].bytes); CHECK(json::from_cbor(cbor_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
const auto ubjson_bytes = json::to_ubjson(jval, false, false, eh::keep); const auto ubjson_bytes = json::to_ubjson(jval, false, false, eh::keep);
CHECK(json::from_ubjson(ubjson_bytes).get<std::string>() == ill_formed_cases[0].bytes); CHECK(json::from_ubjson(ubjson_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
const auto bjdata_bytes = json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, eh::keep); const auto bjdata_bytes = json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, eh::keep);
CHECK(json::from_bjdata(bjdata_bytes).get<std::string>() == ill_formed_cases[0].bytes); CHECK(json::from_bjdata(bjdata_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
const auto msgpack_bytes = json::to_msgpack(jval); const auto msgpack_bytes = json::to_msgpack(jval);
CHECK(json::from_msgpack(msgpack_bytes).get<std::string>() == ill_formed_cases[0].bytes); CHECK(json::from_msgpack(msgpack_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
json bson_obj; json bson_obj;
bson_obj["k"] = jval; bson_obj["k"] = jval;
const auto bson_bytes = json::to_bson(bson_obj, eh::keep); const auto bson_bytes = json::to_bson(bson_obj, eh::keep);
CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == ill_formed_cases[0].bytes); CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == ill_formed_cases()[0].bytes);
} }
} }
+30 -6
View File
@@ -83,21 +83,45 @@ TEST_CASE("JSON_STRICT_BINARY_UTF8 (see #5529, #5651)")
// any bytes reach the output adapter (the BSON document length // any bytes reach the output adapter (the BSON document length
// prefix must be known up front, so nothing is written incrementally) // prefix must be known up front, so nothing is written incrementally)
std::vector<std::uint8_t> out{0x42}; // a sentinel byte the writer must not touch std::vector<std::uint8_t> out{0x42}; // a sentinel byte the writer must not touch
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xFF"}}, nlohmann::detail::output_adapter<std::uint8_t>(out)), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&); #if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}, nlohmann::detail::output_adapter<std::uint8_t>(out)), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
#else
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}, nlohmann::detail::output_adapter<std::uint8_t>(out)), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
#endif
CHECK(out == std::vector<std::uint8_t> {0x42}); CHECK(out == std::vector<std::uint8_t> {0x42});
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xFF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&); #if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
#else
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
#endif
// a truncated multi-byte sequence // a truncated multi-byte sequence
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xC3"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC3", json::type_error&); #if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC3"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xC3", json::type_error&);
#else
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC3"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC3", json::type_error&);
#endif
// an encoded surrogate half (U+D800) // an encoded surrogate half (U+D800)
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xED\xA0\x80"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xED", json::type_error&); #if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xED\xA0\x80"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xED", json::type_error&);
#else
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xED\xA0\x80"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xED", json::type_error&);
#endif
// an overlong encoding of '.' // an overlong encoding of '.'
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xC0\xAF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC0", json::type_error&); #if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC0\xAF"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xC0", json::type_error&);
#else
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC0\xAF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC0", json::type_error&);
#endif
// an object key with ill-formed UTF-8 is rejected as well; unlike // an object key with ill-formed UTF-8 is rejected as well; unlike
// the reader (which never validates element names), the writer // the reader (which never validates element names), the writer
// checks both string values and object keys // checks both string values and object keys
CHECK_THROWS_WITH_AS(json::to_bson(json{{"\xFF", 1}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&); #if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS(json::to_bson(json {{"\xFF", 1}}), "[json.exception.type_error.316] (/\xFF) invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
#else
CHECK_THROWS_WITH_AS(json::to_bson(json {{"\xFF", 1}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
#endif
} }
SECTION("an explicit error_handler overrides the default") SECTION("an explicit error_handler overrides the default")
+1 -39
View File
@@ -9,14 +9,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE #define JSON_TESTS_PRIVATE
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -3929,7 +3921,7 @@ TEST_CASE("Universal Binary JSON Specification Examples 1")
CHECK_NOTHROW(j = json::from_bjdata(v)); CHECK_NOTHROW(j = json::from_bjdata(v));
REQUIRE(j.is_string()); REQUIRE(j.is_string());
CHECK(j.get_ref<const json::string_t&>() == std::string("\xc0\xae")); CHECK(j.get_ref<const json::string_t&>() == std::string("\xc0\xae"));
CHECK_THROWS_AS(j.dump(), json::type_error&); CHECK_THROWS_AS(utils::ignore_return_value(j.dump()), json::type_error&);
CHECK(json::from_bjdata(json::to_bjdata(j)) == j); CHECK(json::from_bjdata(json::to_bjdata(j)) == j);
// the same bytes as an object key round-trip as well // the same bytes as an object key round-trip as well
@@ -4498,33 +4490,3 @@ TEST_CASE("BJData roundtrips" * doctest::skip())
} }
} }
} }
TEST_CASE("issue #5648 - from_bjdata(ptr, len) must read len bytes, not treat ptr as a C string")
{
// to_bjdata() encodes the integer 0 as the two bytes 'i' 0x00 (a BJData
// type marker followed by the value byte 0x00), so the packed data
// below contains a 0x00 byte before its end.
const json j = {{"a", 0}};
const std::vector<std::uint8_t> packed = json::to_bjdata(j);
bool contains_nul = false;
for (const auto byte : packed)
{
contains_nul |= (byte == 0x00);
}
REQUIRE(contains_nul);
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
// before the fix, from_bjdata had no (ptr, len) overload, so this call
// bound to from_bjdata(InputType&&, bool strict) instead: ptr was read
// as a NUL-terminated C string (stopping at the embedded 0x00 byte), and
// len was silently converted to the strict flag. The deprecated
// overload added for this issue forwards to from_bjdata(ptr, ptr + len,
// ...) instead, like from_ubjson's deprecated (ptr, len) overload does.
json result;
CHECK_NOTHROW(result = json::from_bjdata(packed.data(), packed.size()));
CHECK(result == j);
// len must not collapse into the strict flag either
CHECK(json::from_bjdata(packed.data(), packed.size(), false) == j);
#endif
}
+2 -38
View File
@@ -8,14 +8,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
#ifdef JSON_TEST_NO_GLOBAL_UDLS #ifdef JSON_TEST_NO_GLOBAL_UDLS
@@ -794,6 +786,7 @@ TEST_CASE("Parse BON8 directly from a file using iterator and sentinel")
CHECK((parsed.is_object() || parsed.is_array())); CHECK((parsed.is_object() || parsed.is_array()));
} }
#if !defined(JSON_NOEXCEPTION) // corpus values that do not survive the round trip are skipped by catching the exception
TEST_CASE("BON8 round-trip invariants") TEST_CASE("BON8 round-trip invariants")
{ {
// This checks what the parse_bon8_fuzzer driver checks (see // This checks what the parse_bon8_fuzzer driver checks (see
@@ -826,6 +819,7 @@ TEST_CASE("BON8 round-trip invariants")
CHECK(json::to_bon8(j2) == vec); CHECK(json::to_bon8(j2) == vec);
} }
} }
#endif
TEST_CASE("BON8 roundtrips" * doctest::skip()) TEST_CASE("BON8 roundtrips" * doctest::skip())
{ {
@@ -1020,36 +1014,6 @@ TEST_CASE("BON8 roundtrips" * doctest::skip())
} }
} }
TEST_CASE("issue #5648 - from_bon8(ptr, len) must read len bytes, not treat ptr as a C string")
{
// to_bon8() encodes the integer 40 as the two bytes 0xC2 0x00 (a BON8
// lead byte followed by a continuation byte of 0x00), so the packed data
// below contains a 0x00 byte before its end.
const json j = {{"a", 40}, {"b", "x"}};
const std::vector<std::uint8_t> packed = json::to_bon8(j);
bool contains_nul = false;
for (const auto byte : packed)
{
contains_nul |= (byte == 0x00);
}
REQUIRE(contains_nul);
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
// before the fix, from_bon8 had no (ptr, len) overload, so this call
// bound to from_bon8(InputType&&, bool strict) instead: ptr was read as
// a NUL-terminated C string (stopping at the embedded 0x00 byte), and
// len was silently converted to the strict flag. The deprecated
// overload added for this issue forwards to from_bon8(ptr, ptr + len,
// ...) instead, like from_cbor's deprecated (ptr, len) overload does.
json result;
CHECK_NOTHROW(result = json::from_bon8(packed.data(), packed.size()));
CHECK(result == j);
// len must not collapse into the strict flag either
CHECK(json::from_bon8(packed.data(), packed.size(), false) == j);
#endif
}
#ifdef JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17
TEST_CASE("BON8 with std::byte") TEST_CASE("BON8 with std::byte")
{ {
+3 -13
View File
@@ -8,14 +8,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -70,6 +62,8 @@ class huge_string_t : public std::string
{ {
public: public:
using std::string::string; using std::string::string;
// inheriting std::string's constructors does not inherit its default constructor
huge_string_t() = default;
huge_string_t(const std::string& s) : std::string(s) {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) huge_string_t(const std::string& s) : std::string(s) {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
// returns a copy of @a s whose size() pretends to be huge // returns a copy of @a s whose size() pretends to be huge
@@ -182,7 +176,7 @@ TEST_CASE("BSON")
REQUIRE(j.contains("s")); REQUIRE(j.contains("s"));
CHECK(j["s"].get_ref<const json::string_t&>() == std::string("\xc0\xae")); CHECK(j["s"].get_ref<const json::string_t&>() == std::string("\xc0\xae"));
// dump() still requires valid UTF-8 and throws for such a value // dump() still requires valid UTF-8 and throws for such a value
CHECK_THROWS_AS(j.dump(), json::type_error&); CHECK_THROWS_AS(utils::ignore_return_value(j.dump()), json::type_error&);
// to_bson() writes the bytes back unchanged, as before 3.13.0, // to_bson() writes the bytes back unchanged, as before 3.13.0,
// unless JSON_STRICT_BINARY_UTF8 is enabled (see unit-binary_utf8_strict.cpp) // unless JSON_STRICT_BINARY_UTF8 is enabled (see unit-binary_utf8_strict.cpp)
CHECK(json::from_bson(json::to_bson(j)) == j); CHECK(json::from_bson(json::to_bson(j)) == j);
@@ -1267,10 +1261,8 @@ TEST_CASE("BSON input that cannot be read is discarded by every overload")
CHECK_THROWS_AS(_ = json::from_bson(input.begin(), input.end()), json::parse_error&); CHECK_THROWS_AS(_ = json::from_bson(input.begin(), input.end()), json::parse_error&);
CHECK(json::from_bson(input, true, false).is_discarded()); CHECK(json::from_bson(input, true, false).is_discarded());
CHECK(json::from_bson(input.begin(), input.end(), true, false).is_discarded()); CHECK(json::from_bson(input.begin(), input.end(), true, false).is_discarded());
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
CHECK(json::from_bson(input.data(), input.size(), true, false).is_discarded()); CHECK(json::from_bson(input.data(), input.size(), true, false).is_discarded());
CHECK(json::from_bson({input.data(), input.size()}, true, false).is_discarded()); CHECK(json::from_bson({input.data(), input.size()}, true, false).is_discarded());
#endif
} }
TEST_CASE("BSON SAX parsing stops at every event") TEST_CASE("BSON SAX parsing stops at every event")
@@ -1748,7 +1740,6 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
{ {
INFO_WITH_TEMP(filename + ": uint8_t* and size"); INFO_WITH_TEMP(filename + ": uint8_t* and size");
// parse JSON file // parse JSON file
@@ -1763,7 +1754,6 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
// compare parsed JSON values // compare parsed JSON values
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#endif
{ {
INFO_WITH_TEMP(filename + ": output to output adapters"); INFO_WITH_TEMP(filename + ": output to output adapters");
+5 -15
View File
@@ -8,14 +8,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -1828,7 +1820,7 @@ TEST_CASE("CBOR")
// dump() still requires valid UTF-8 and throws for such a value, // dump() still requires valid UTF-8 and throws for such a value,
// unless an error handler that replaces or ignores the bytes is // unless an error handler that replaces or ignores the bytes is
// passed // passed
CHECK_THROWS_AS(j_value.dump(), json::type_error&); CHECK_THROWS_AS(utils::ignore_return_value(j_value.dump()), json::type_error&);
// to_cbor() writes the bytes back unchanged, as before 3.13.0, // to_cbor() writes the bytes back unchanged, as before 3.13.0,
// unless JSON_STRICT_BINARY_UTF8 is enabled (see unit-binary_utf8_strict.cpp) // unless JSON_STRICT_BINARY_UTF8 is enabled (see unit-binary_utf8_strict.cpp)
CHECK(json::from_cbor(json::to_cbor(j_value)) == j_value); CHECK(json::from_cbor(json::to_cbor(j_value)) == j_value);
@@ -1886,13 +1878,13 @@ TEST_CASE("CBOR")
// a truncated code point is kept as is // a truncated code point is kept as is
CHECK_NOTHROW(_ = json::from_cbor(std::vector<uint8_t>({0x7f, 0x61, 0xc3, 0xff}))); CHECK_NOTHROW(_ = json::from_cbor(std::vector<uint8_t>({0x7f, 0x61, 0xc3, 0xff})));
CHECK(_ == "\xc3"); CHECK(_ == "\xc3");
CHECK_THROWS_AS(_.dump(), json::type_error&); CHECK_THROWS_AS(utils::ignore_return_value(_.dump()), json::type_error&);
CHECK(json::from_cbor(json::to_cbor(_)) == _); CHECK(json::from_cbor(json::to_cbor(_)) == _);
// an ill-formed later chunk is kept after valid ones // an ill-formed later chunk is kept after valid ones
CHECK_NOTHROW(_ = json::from_cbor(std::vector<uint8_t>({0x7f, 0x62, 0xc3, 0xa9, 0x62, 0xc0, 0xae, 0xff}))); CHECK_NOTHROW(_ = json::from_cbor(std::vector<uint8_t>({0x7f, 0x62, 0xc3, 0xa9, 0x62, 0xc0, 0xae, 0xff})));
CHECK(_ == "\xc3\xa9\xc0\xae"); CHECK(_ == "\xc3\xa9\xc0\xae");
CHECK_THROWS_AS(_.dump(), json::type_error&); CHECK_THROWS_AS(utils::ignore_return_value(_.dump()), json::type_error&);
// valid multi-byte chunks are accepted // valid multi-byte chunks are accepted
CHECK(json::from_cbor(std::vector<uint8_t>({0x7f, 0x62, 0xc3, 0xa9, 0x62, 0xc3, 0xb6, 0xff})) == "\xc3\xa9\xc3\xb6"); CHECK(json::from_cbor(std::vector<uint8_t>({0x7f, 0x62, 0xc3, 0xa9, 0x62, 0xc3, 0xb6, 0xff})) == "\xc3\xa9\xc3\xb6");
@@ -2223,10 +2215,8 @@ TEST_CASE("CBOR input that cannot be read is discarded by every overload")
CHECK_THROWS_AS(_ = json::from_cbor(input.begin(), input.end()), json::parse_error&); CHECK_THROWS_AS(_ = json::from_cbor(input.begin(), input.end()), json::parse_error&);
CHECK(json::from_cbor(input, true, false).is_discarded()); CHECK(json::from_cbor(input, true, false).is_discarded());
CHECK(json::from_cbor(input.begin(), input.end(), true, false).is_discarded()); CHECK(json::from_cbor(input.begin(), input.end(), true, false).is_discarded());
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
CHECK(json::from_cbor(input.data(), input.size(), true, false).is_discarded()); CHECK(json::from_cbor(input.data(), input.size(), true, false).is_discarded());
CHECK(json::from_cbor({input.data(), input.size()}, true, false).is_discarded()); CHECK(json::from_cbor({input.data(), input.size()}, true, false).is_discarded());
#endif
// a string that ends early, read through iterators that are not // a string that ends early, read through iterators that are not
// contiguous and have to be copied from one element at a time // contiguous and have to be copied from one element at a time
@@ -2400,6 +2390,7 @@ TEST_CASE("issue #5405 - array reserve for definite-length CBOR arrays")
} }
} }
#if !defined(JSON_NOEXCEPTION) // corpus values that do not survive the round trip are skipped by catching the exception
TEST_CASE("CBOR round-trip invariants") TEST_CASE("CBOR round-trip invariants")
{ {
// This checks what the parse_cbor_fuzzer driver checks (see // This checks what the parse_cbor_fuzzer driver checks (see
@@ -2432,6 +2423,7 @@ TEST_CASE("CBOR round-trip invariants")
CHECK(json::to_cbor(j2) == vec); CHECK(json::to_cbor(j2) == vec);
} }
} }
#endif
TEST_CASE("CBOR roundtrips" * doctest::skip()) TEST_CASE("CBOR roundtrips" * doctest::skip())
{ {
@@ -2621,14 +2613,12 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
{ {
INFO_WITH_TEMP(filename + ": uint8_t* and size"); INFO_WITH_TEMP(filename + ": uint8_t* and size");
json j2; json j2;
CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()})); CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()}));
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#endif
{ {
INFO_WITH_TEMP(filename + ": output to output adapters"); INFO_WITH_TEMP(filename + ": output to output adapters");
+3 -3
View File
@@ -2704,9 +2704,9 @@ TEST_CASE("diagnostic positions: value lifetime, input adapters, and SAX")
CHECK(b["b"].end_pos() == nested_end); CHECK(b["b"].end_pos() == nested_end);
// the moved-from value is reset to a null and reports npos // the moved-from value is reset to a null and reports npos
CHECK(a.is_null()); // NOLINT(bugprone-use-after-move,clang-analyzer-cplusplus.Move) CHECK(a.is_null()); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
CHECK(a.start_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,clang-analyzer-cplusplus.Move) CHECK(a.start_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
CHECK(a.end_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,clang-analyzer-cplusplus.Move) CHECK(a.end_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
} }
SECTION("swap() exchanges positions along with values") SECTION("swap() exchanges positions along with values")
+2 -2
View File
@@ -969,7 +969,7 @@ TEST_CASE("copying an object preserves its comparator's state")
for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200}) for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200})
{ {
CAPTURE(depth); CAPTURE(depth)
key_case_json original = object; key_case_json original = object;
for (std::size_t i = 0; i < depth; ++i) for (std::size_t i = 0; i < depth; ++i)
@@ -1138,7 +1138,7 @@ TEST_CASE("operator<=> of binary values with a different subtype does not depend
// and must still agree with the levels that do // and must still agree with the levels that do
for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200}) for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200})
{ {
CAPTURE(depth); CAPTURE(depth)
const json x = deep(a, depth); const json x = deep(a, depth);
const json y = deep(b, depth); const json y = deep(b, depth);
CHECK((x <=> y) == std::partial_ordering::less); // *NOPAD* CHECK((x <=> y) == std::partial_ordering::less); // *NOPAD*
@@ -15,11 +15,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// skip tests if JSON_DisableEnumSerialization=ON (#4384)
#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1)
#define SKIP_TESTS_FOR_ENUM_SERIALIZATION
#endif
#define JSON_TESTS_PRIVATE #define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -1259,808 +1254,8 @@ TEST_CASE("value conversion")
} }
} }
#endif #endif
SECTION("get a binary value (explicit)")
{
json::binary_t const n_reference{{1, 2, 3}};
json j(n_reference);
SECTION("binary_t")
{
json::binary_t const b = j.get<json::binary_t>();
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
SECTION("get_binary()")
{
SECTION("non-const")
{
auto& b = j.get_binary();
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
SECTION("non-const")
{
const json j_const = j; // NOLINT(performance-unnecessary-copy-initialization)
const auto& b = j_const.get_binary();
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
}
SECTION("exception in case of a non-string type")
{
json j_null(json::value_t::null);
json j_object(json::value_t::object);
json j_array(json::value_t::array);
json j_string(json::value_t::string);
json j_boolean(json::value_t::boolean);
const json j_null_const(json::value_t::null);
const json j_object_const(json::value_t::object);
const json j_array_const(json::value_t::array);
const json j_string_const(json::value_t::string);
const json j_boolean_const(json::value_t::boolean);
CHECK_THROWS_WITH_AS(j_null.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
CHECK_THROWS_WITH_AS(j_null_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
CHECK_THROWS_WITH_AS(j_null.get_binary(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object.get_binary(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array.get_binary(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string.get_binary(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean.get_binary(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
CHECK_THROWS_WITH_AS(j_null_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
}
}
#if JSON_USE_IMPLICIT_CONVERSIONS
SECTION("get a binary value (implicit)")
{
json::binary_t const n_reference{{1, 2, 3}};
json const j(n_reference);
SECTION("binary_t")
{
json::binary_t const b = j;
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
}
#endif
#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION
SECTION("get an enum")
{
enum c_enum { value_1, value_2 }; // NOLINT(cppcoreguidelines-use-enum-class)
enum class cpp_enum { value_1, value_2 };
CHECK(json(value_1).get<c_enum>() == value_1);
CHECK(json(cpp_enum::value_1).get<cpp_enum>() == cpp_enum::value_1);
}
SECTION("get an enum with underlying type bool (#5671)")
{
enum class bool_enum : bool { off, on };
CHECK(json(bool_enum::off).get<bool_enum>() == bool_enum::off);
CHECK(json(bool_enum::on).get<bool_enum>() == bool_enum::on);
}
#endif
SECTION("more involved conversions")
{
SECTION("object-like STL containers")
{
json const j1 = {{"one", 1}, {"two", 2}, {"three", 3}};
json const j2 = {{"one", 1u}, {"two", 2u}, {"three", 3u}};
json const j3 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
json const j4 = {{"one", true}, {"two", false}, {"three", true}};
json const j5 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
SECTION("std::map")
{
CHECK(j1.get<std::map<std::string, int>>() == (std::map<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::map<std::string, unsigned int>>() == (std::map<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::map<std::string, double>>() == (std::map<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::map<std::string, bool>>() == (std::map<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
CHECK(j5.get<std::map<std::string, std::string>>() == (std::map<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
}
SECTION("std::unordered_map")
{
CHECK(j1.get<std::unordered_map<std::string, int>>() == (std::unordered_map<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::unordered_map<std::string, unsigned int>>() == (std::unordered_map<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::unordered_map<std::string, double>>() == (std::unordered_map<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::unordered_map<std::string, bool>>() == (std::unordered_map<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
const auto m5 = j5.get<std::unordered_map<std::string, std::string>>();
CHECK(m5 == (std::unordered_map<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
CHECK(m5.at("one") == "eins");
}
SECTION("reserve is called on containers that support it (#5406)")
{
// build a larger object so that a missing/incorrect reserve()
// call would be more likely to corrupt or drop elements
json j_large;
for (int i = 0; i < 100; ++i)
{
j_large[std::to_string(i)] = i;
}
SECTION("std::unordered_map (supports reserve)")
{
const auto m = j_large.get<std::unordered_map<std::string, int>>();
CHECK(m.size() == 100);
for (int i = 0; i < 100; ++i)
{
CHECK(m.at(std::to_string(i)) == i);
}
}
SECTION("std::map (no reserve, fallback path)")
{
const auto m = j_large.get<std::map<std::string, int>>();
CHECK(m.size() == 100);
for (int i = 0; i < 100; ++i)
{
CHECK(m.at(std::to_string(i)) == i);
}
}
}
SECTION("std::multimap")
{
CHECK(j1.get<std::multimap<std::string, int>>() == (std::multimap<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::multimap<std::string, unsigned int>>() == (std::multimap<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::multimap<std::string, double>>() == (std::multimap<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::multimap<std::string, bool>>() == (std::multimap<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
const auto m5 = j5.get<std::multimap<std::string, std::string>>();
CHECK(m5 == (std::multimap<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
CHECK(m5.find("one")->second == "eins");
}
SECTION("std::unordered_multimap")
{
CHECK(j1.get<std::unordered_multimap<std::string, int>>() == (std::unordered_multimap<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::unordered_multimap<std::string, unsigned int>>() == (std::unordered_multimap<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::unordered_multimap<std::string, double>>() == (std::unordered_multimap<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::unordered_multimap<std::string, bool>>() == (std::unordered_multimap<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
const auto m5 = j5.get<std::unordered_multimap<std::string, std::string>>();
CHECK(m5 == (std::unordered_multimap<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
CHECK(m5.find("one")->second == "eins");
}
SECTION("exception in case of a non-object type")
{
CHECK_THROWS_WITH_AS(
(json().get<std::map<std::string, int>>()),
"[json.exception.type_error.302] type must be object, but is null", json::type_error&);
}
}
SECTION("array-like STL containers")
{
json const j1 = {1, 2, 3, 4};
json const j2 = {1u, 2u, 3u, 4u};
json const j3 = {1.2, 2.3, 3.4, 4.5};
json const j4 = {true, false, true};
json const j5 = {"one", "two", "three"};
SECTION("std::list")
{
CHECK(j1.get<std::list<int>>() == (std::list<int> {1, 2, 3, 4}));
CHECK(j2.get<std::list<unsigned int>>() == (std::list<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::list<double>>() == (std::list<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::list<bool>>() == (std::list<bool> {true, false, true}));
CHECK(j5.get<std::list<std::string>>() == (std::list<std::string> {"one", "two", "three"}));
}
SECTION("std::forward_list")
{
CHECK(j1.get<std::forward_list<int>>() == (std::forward_list<int> {1, 2, 3, 4}));
CHECK(j2.get<std::forward_list<unsigned int>>() == (std::forward_list<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::forward_list<double>>() == (std::forward_list<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::forward_list<bool>>() == (std::forward_list<bool> {true, false, true}));
CHECK(j5.get<std::forward_list<std::string>>() == (std::forward_list<std::string> {"one", "two", "three"}));
}
SECTION("std::array")
{
CHECK(j1.get<std::array<int, 4>>() == (std::array<int, 4> {{1, 2, 3, 4}}));
// only the first 3 elements of j2 are converted, since the target array is smaller
CHECK(j2.get<std::array<unsigned int, 3>>() == (std::array<unsigned int, 3> {{1u, 2u, 3u}}));
CHECK(j3.get<std::array<double, 4>>() == (std::array<double, 4> {{1.2, 2.3, 3.4, 4.5}}));
CHECK(j4.get<std::array<bool, 3>>() == (std::array<bool, 3> {{true, false, true}}));
CHECK(j5.get<std::array<std::string, 3>>() == (std::array<std::string, 3> {{"one", "two", "three"}}));
SECTION("std::array is larger than JSON")
{
std::array<int, 6> arr6 = {{1, 2, 3, 4, 5, 6}};
CHECK_THROWS_WITH_AS(j1.get_to(arr6), "[json.exception.out_of_range.401] "
"array index 4 is out of range", json::out_of_range&);
}
SECTION("std::array is smaller than JSON")
{
std::array<int, 2> arr2 = {{8, 9}};
j1.get_to(arr2);
CHECK(arr2[0] == 1);
CHECK(arr2[1] == 2);
}
}
SECTION("std::valarray")
{
// valarray has no operator== that returns bool, so compare via a vector copy
const auto v1 = j1.get<std::valarray<int>>();
CHECK((std::vector<int>(std::begin(v1), std::end(v1)) == std::vector<int> {1, 2, 3, 4}));
const auto v2 = j2.get<std::valarray<unsigned int>>();
CHECK((std::vector<unsigned int>(std::begin(v2), std::end(v2)) == std::vector<unsigned int> {1u, 2u, 3u, 4u}));
const auto v3 = j3.get<std::valarray<double>>();
CHECK((std::vector<double>(std::begin(v3), std::end(v3)) == std::vector<double> {1.2, 2.3, 3.4, 4.5}));
const auto v4 = j4.get<std::valarray<bool>>();
CHECK((std::vector<bool>(std::begin(v4), std::end(v4)) == std::vector<bool> {true, false, true}));
const auto v5 = j5.get<std::valarray<std::string>>();
CHECK((std::vector<std::string>(std::begin(v5), std::end(v5)) == std::vector<std::string> {"one", "two", "three"}));
}
SECTION("std::vector")
{
CHECK(j1.get<std::vector<int>>() == (std::vector<int> {1, 2, 3, 4}));
CHECK(j2.get<std::vector<unsigned int>>() == (std::vector<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::vector<double>>() == (std::vector<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::vector<bool>>() == (std::vector<bool> {true, false, true}));
CHECK(j5.get<std::vector<std::string>>() == (std::vector<std::string> {"one", "two", "three"}));
}
SECTION("std::deque")
{
CHECK(j1.get<std::deque<int>>() == (std::deque<int> {1, 2, 3, 4}));
CHECK(j2.get<std::deque<unsigned int>>() == (std::deque<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::deque<double>>() == (std::deque<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::deque<bool>>() == (std::deque<bool> {true, false, true}));
CHECK(j5.get<std::deque<std::string>>() == (std::deque<std::string> {"one", "two", "three"}));
}
SECTION("std::set")
{
CHECK(j1.get<std::set<int>>() == (std::set<int> {1, 2, 3, 4}));
CHECK(j2.get<std::set<unsigned int>>() == (std::set<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::set<double>>() == (std::set<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::set<bool>>() == (std::set<bool> {true, false, true}));
CHECK(j5.get<std::set<std::string>>() == (std::set<std::string> {"one", "two", "three"}));
}
SECTION("std::unordered_set")
{
CHECK(j1.get<std::unordered_set<int>>() == (std::unordered_set<int> {1, 2, 3, 4}));
CHECK(j2.get<std::unordered_set<unsigned int>>() == (std::unordered_set<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::unordered_set<double>>() == (std::unordered_set<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::unordered_set<bool>>() == (std::unordered_set<bool> {true, false, true}));
CHECK(j5.get<std::unordered_set<std::string>>() == (std::unordered_set<std::string> {"one", "two", "three"}));
}
SECTION("std::map (array of pairs)")
{
const std::map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
json const j6 = m;
auto m2 = j6.get<std::map<int, int>>();
CHECK(m == m2);
json const j7 = {0, 1, 2, 3};
json const j8 = 2;
#if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS((j7.get<std::map<int, int>>()),
"[json.exception.type_error.302] (/0) type must be array, "
"but is number", json::type_error&);
#else
CHECK_THROWS_WITH_AS((j7.get<std::map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
#endif
CHECK_THROWS_WITH_AS((j8.get<std::map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
SECTION("superfluous entries")
{
json const j9 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
m2 = j9.get<std::map<int, int>>();
CHECK(m == m2);
}
}
SECTION("std::unordered_map (array of pairs)")
{
const std::unordered_map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
json const j6 = m;
auto m2 = j6.get<std::unordered_map<int, int>>();
CHECK(m == m2);
json const j7 = {0, 1, 2, 3};
json const j8 = 2;
#if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS((j7.get<std::unordered_map<int, int>>()),
"[json.exception.type_error.302] (/0) type must be array, "
"but is number", json::type_error&);
#else
CHECK_THROWS_WITH_AS((j7.get<std::unordered_map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
#endif
CHECK_THROWS_WITH_AS((j8.get<std::unordered_map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
SECTION("superfluous entries")
{
json const j9{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
m2 = j9.get<std::unordered_map<int, int>>();
CHECK(m == m2);
}
}
SECTION("exception in case of a non-object type")
{
// does type really must be an array? or it rather must not be null?
// that's what I thought when other test like this one broke
CHECK_THROWS_WITH_AS(
(json().get<std::list<int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::vector<int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::vector<json>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::list<json>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::valarray<int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::map<int, int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
}
}
}
} }
enum class cards {kreuz, pik, herz, karo};
// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM(cards,
{
{cards::kreuz, "kreuz"},
{cards::pik, "pik"},
{cards::pik, "puk"}, // second entry for cards::puk; will not be used
{cards::herz, "herz"},
{cards::karo, "karo"}
})
enum TaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class)
{
TS_STOPPED,
TS_RUNNING,
TS_COMPLETED,
TS_INVALID = -1,
};
// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM(TaskState,
{
{TS_INVALID, nullptr},
{TS_STOPPED, "stopped"},
{TS_RUNNING, "running"},
{TS_COMPLETED, "completed"},
})
TEST_CASE("JSON to enum mapping")
{
SECTION("enum class")
{
// enum -> json
CHECK(json(cards::kreuz) == "kreuz");
CHECK(json(cards::pik) == "pik");
CHECK(json(cards::herz) == "herz");
CHECK(json(cards::karo) == "karo");
// json -> enum
CHECK(cards::kreuz == json("kreuz"));
CHECK(cards::pik == json("pik"));
CHECK(cards::herz == json("herz"));
CHECK(cards::karo == json("karo"));
// invalid json -> first enum
CHECK(cards::kreuz == json("what?").get<cards>());
}
SECTION("traditional enum")
{
// enum -> json
CHECK(json(TS_STOPPED) == "stopped");
CHECK(json(TS_RUNNING) == "running");
CHECK(json(TS_COMPLETED) == "completed");
CHECK(json(TS_INVALID) == json());
// json -> enum
CHECK(TS_STOPPED == json("stopped"));
CHECK(TS_RUNNING == json("running"));
CHECK(TS_COMPLETED == json("completed"));
CHECK(TS_INVALID == json());
// invalid json -> first enum
CHECK(TS_INVALID == json("what?").get<TaskState>());
}
}
enum class strict_cards {kreuz, pik, herz, karo, andere}; // andere not included in mapping
// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(strict_cards,
{
{strict_cards::kreuz, "kreuz"},
{strict_cards::pik, "pik"},
{strict_cards::pik, "puk"}, // second entry for cards::pik; will not be used
{strict_cards::herz, "herz"},
{strict_cards::karo, "karo"}
})
enum StrictTaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class)
{
STRICT_TS_STOPPED,
STRICT_TS_RUNNING,
STRICT_TS_COMPLETED,
STRICT_TS_OTHER, // STRICT_TS_OTHER not in mapping
STRICT_TS_INVALID = -1,
};
// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(StrictTaskState,
{
{STRICT_TS_INVALID, nullptr},
{STRICT_TS_STOPPED, "stopped"},
{STRICT_TS_RUNNING, "running"},
{STRICT_TS_COMPLETED, "completed"},
})
// regression test for #5708 item 2: NLOHMANN_JSON_SERIALIZE_ENUM_STRICT must not rely on
// unqualified lookup of a helper name that a user's own namespace may also declare
namespace ns_with_colliding_name
{
// NOLINTNEXTLINE(misc-use-internal-linkage) - used to shadow the library's internal helper name
inline void templated_json_throw(int /*unused*/) {}
enum class colliding_enum { a, b };
// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(colliding_enum,
{
{colliding_enum::a, "a"},
{colliding_enum::b, "b"}
})
} // namespace ns_with_colliding_name
TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT in a namespace with a colliding name")
{
using ns_with_colliding_name::colliding_enum;
CHECK(json(colliding_enum::a) == "a");
CHECK(colliding_enum::b == json("b"));
json _;
CHECK_THROWS_WITH_AS(_ = json("nope").get<colliding_enum>(), "[json.exception.out_of_range.410] enum value out of range for colliding_enum: \"nope\"", json::out_of_range&);
}
TEST_CASE("Strict JSON to enum mapping")
{
SECTION("enum class")
{
// enum -> json
CHECK(json(strict_cards::kreuz) == "kreuz");
CHECK(json(strict_cards::pik) == "pik");
CHECK(json(strict_cards::herz) == "herz");
CHECK(json(strict_cards::karo) == "karo");
// json -> enum
CHECK(json("kreuz").get<strict_cards>() == strict_cards::kreuz);
CHECK(json("pik").get<strict_cards>() == strict_cards::pik);
CHECK(json("herz").get<strict_cards>() == strict_cards::herz);
CHECK(json("karo").get<strict_cards>() == strict_cards::karo);
// comparison of enum and json
CHECK(strict_cards::kreuz == json("kreuz"));
CHECK(strict_cards::pik == json("pik"));
CHECK(strict_cards::herz == json("herz"));
CHECK(strict_cards::karo == json("karo"));
// invalid json -> exception thrown
json _;
CHECK_THROWS_WITH_AS(_ = json("what?").get<strict_cards>(), "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"what?\"", json::out_of_range&);
// conversion of unmapped enum -> exception thrown
CHECK_THROWS_WITH_AS(json(strict_cards::andere), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&);
// comparing an unmapped enum with json throws the same exception
// (the scalar comparison operators used to be noexcept, so this
// called std::terminate)
CHECK_THROWS_WITH_AS(static_cast<void>(strict_cards::andere == json("andere")), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&);
CHECK_THROWS_WITH_AS(static_cast<void>(json("andere") != strict_cards::andere), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&);
// invalid UTF-8 -> out_of_range.410, not the type_error.316 thrown while building the
// message (regression test for #5667); such strings can reach get<Enum>() unvalidated,
// e.g. from from_cbor()/from_msgpack() (#5529)
const json j_invalid_utf8 = "\xFF";
CHECK_THROWS_WITH_AS(_ = j_invalid_utf8.get<strict_cards>(), "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"\xEF\xBF\xBD\"", json::out_of_range&);
}
SECTION("traditional enum")
{
// enum -> json
CHECK(json(STRICT_TS_STOPPED) == "stopped");
CHECK(json(STRICT_TS_RUNNING) == "running");
CHECK(json(STRICT_TS_COMPLETED) == "completed");
CHECK(json(STRICT_TS_INVALID) == json());
// json -> enum
CHECK(json("stopped").get<StrictTaskState>() == STRICT_TS_STOPPED);
CHECK(json("running").get<StrictTaskState>() == STRICT_TS_RUNNING);
CHECK(json("completed").get<StrictTaskState>() == STRICT_TS_COMPLETED);
CHECK(json().get<StrictTaskState>() == STRICT_TS_INVALID);
// comparison of enum and json
CHECK(STRICT_TS_STOPPED == json("stopped"));
CHECK(STRICT_TS_RUNNING == json("running"));
CHECK(STRICT_TS_COMPLETED == json("completed"));
CHECK(STRICT_TS_INVALID == json());
// invalid json -> exception thrown
json _;
CHECK_THROWS_WITH_AS(_ = json("what?").get<StrictTaskState>(), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState: \"what?\"", json::out_of_range&);
// conversion of unmapped enum -> exception thrown
CHECK_THROWS_WITH_AS(json(STRICT_TS_OTHER), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState", json::out_of_range&);
// comparing an unmapped enum with json throws the same exception
CHECK_THROWS_WITH_AS(static_cast<void>(STRICT_TS_OTHER < json("x")), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState", json::out_of_range&);
}
}
#ifdef JSON_HAS_CPP_17
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
TEST_CASE("std::filesystem::path")
{
SECTION("ascii")
{
json const j_string = "Path";
auto p = j_string.template get<nlohmann::detail::std_fs::path>();
json const j_path = p;
CHECK(j_path.template get<std::string>() ==
j_string.template get<std::string>());
}
SECTION("utf-8")
{
json const j_string = "P\xc4\x9b\xc5\xa1ina";
auto p = j_string.template get<nlohmann::detail::std_fs::path>();
json const j_path = p;
CHECK(j_path.template get<std::string>() ==
j_string.template get<std::string>());
}
}
#endif
// the ADL to_json overload for std::u8string only exists under the same guard
// as std::filesystem::path support (it is otherwise only reached indirectly,
// via std::filesystem::path::u8string()) -- mirror both #if conditions from
// include/nlohmann/detail/conversions/to_json.hpp exactly
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
#if defined(__cpp_lib_char8_t)
TEST_CASE("std::u8string")
{
SECTION("ascii")
{
const std::u8string s = u8"Path";
json const j = s;
CHECK(j.template get<std::string>() == "Path");
}
SECTION("utf-8")
{
// use \u universal-character-names (rather than raw \x byte escapes
// or literal non-ASCII source bytes) to compose the multi-byte UTF-8
// encoding -- MSVC treats \x escapes used that way inside a u8
// literal as a nonstandard extension (warning C5321), which some of
// our CI configs promote to an error; \u is portable and produces
// the exact same encoded bytes without depending on the source
// file's encoding
const std::u8string s = u8"P\u011B\u0161ina";
json const j = s;
CHECK(j.template get<std::string>() == "P\xc4\x9b\xc5\xa1ina");
}
}
#endif
#endif
#if !defined(JSON_NOEXCEPTION)
namespace
{
// a type whose to_json reports an error by throwing, used below to check that
// converting a std::optional<T> to JSON propagates an exception thrown while
// converting its contained value instead of calling std::terminate (#5642)
struct throwing_to_json_type {};
[[noreturn]] void to_json(json& /*unused*/, const throwing_to_json_type& /*unused*/)
{
throw std::runtime_error("cannot serialize throwing_to_json_type");
}
} // namespace
#endif
TEST_CASE("std::optional")
{
SECTION("null")
{
const json j_null;
const std::optional<std::string> opt_null;
CHECK(json(opt_null) == j_null);
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&);
// Assignment goes through the same overload resolution as direct
// construction, so it throws for the same reason. This relies on
// basic_json's implicit conversion operator, so it only applies
// when JSON_USE_IMPLICIT_CONVERSIONS is enabled (the default).
#if JSON_USE_IMPLICIT_CONVERSIONS
std::optional<std::string> opt_assign;
CHECK_THROWS_WITH_AS(opt_assign = j_null,
"[json.exception.type_error.302] type must be string, but is null", json::type_error&);
#endif
// get_to() is the correct way to obtain std::nullopt from a JSON null.
std::optional<std::string> opt_get_to = "placeholder";
j_null.get_to(opt_get_to);
CHECK(opt_get_to == std::nullopt);
}
SECTION("string")
{
json j_string = "string";
std::optional<std::string> opt_string = "string";
CHECK(json(opt_string) == j_string);
CHECK(std::optional<std::string>(j_string) == opt_string);
// false positive: Infer attributes the destruction of the temporaries above to opt_string
// @infer-ignore USE_AFTER_DELETE
}
SECTION("bool")
{
json j_bool = true;
std::optional<bool> opt_bool = true;
CHECK(json(opt_bool) == j_bool);
CHECK(std::optional<bool>(j_bool) == opt_bool);
}
SECTION("number")
{
json j_number = 1;
std::optional<int> opt_int = 1;
CHECK(json(opt_int) == j_number);
CHECK(j_number.get<std::optional<int>>() == opt_int);
}
SECTION("array")
{
json j_array = {1, 2, nullptr};
std::vector<std::optional<int>> opt_array = {{1, 2, std::nullopt}};
CHECK(json(opt_array) == j_array);
CHECK(j_array.get<std::vector<std::optional<int>>>() == opt_array);
}
SECTION("object")
{
json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}};
std::map<std::string, std::optional<int>> opt_object {{"one", 1}, {"two", 2}, {"zero", std::nullopt}};
CHECK(json(opt_object) == j_object);
CHECK(std::map<std::string, std::optional<int>>(j_object) == opt_object);
}
#if !defined(JSON_NOEXCEPTION)
SECTION("exception from contained value's to_json propagates (#5642)")
{
// to_json(BasicJsonType&, const std::optional<T>&) must not be
// noexcept: it calls T's to_json, which may throw (a user-defined
// to_json that reports an error, or std::bad_alloc for T =
// std::string/vector/json). Before the fix, this called
// std::terminate() instead of letting the exception propagate.
const std::optional<throwing_to_json_type> opt = throwing_to_json_type{};
CHECK_THROWS_WITH_AS(json(opt), "cannot serialize throwing_to_json_type", std::runtime_error&);
// the conversion is noexcept exactly when converting the contained value is
static_assert(!std::is_nothrow_constructible<json, const std::optional<throwing_to_json_type>&>::value);
static_assert(std::is_nothrow_constructible<json, const std::optional<int>&>::value);
}
#endif
}
#endif
#ifdef JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_17 #undef JSON_HAS_CPP_17
#endif #endif
+868
View File
@@ -0,0 +1,868 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// cmake/test.cmake selects the C++ standard versions with which to build a
// unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
// When using macros that are only defined for particular versions of the standard
// (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
// version macro in a comment close by, like this:
// JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
#include "doctest_compatibility.h"
// skip tests if JSON_DisableEnumSerialization=ON (#4384)
#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1)
#define SKIP_TESTS_FOR_ENUM_SERIALIZATION
#endif
#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <deque>
#include <forward_list>
#include <list>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
#define JSON_HAS_CPP_17
#define JSON_HAS_CPP_14
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
#define JSON_HAS_CPP_14
#endif
#ifdef JSON_HAS_CPP_17
#if __has_include(<optional>)
#include <optional>
#elif __has_include(<experimental/optional>)
#include <experimental/optional>
#endif
#endif
#if defined(JSON_HAS_CPP_17)
#include <string_view>
#endif
TEST_CASE("value conversion")
{
SECTION("get a binary value (explicit)")
{
json::binary_t const n_reference{{1, 2, 3}};
json j(n_reference);
SECTION("binary_t")
{
json::binary_t const b = j.get<json::binary_t>();
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
SECTION("get_binary()")
{
SECTION("non-const")
{
auto& b = j.get_binary();
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
SECTION("non-const")
{
const json j_const = j; // NOLINT(performance-unnecessary-copy-initialization)
const auto& b = j_const.get_binary();
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
}
SECTION("exception in case of a non-string type")
{
json j_null(json::value_t::null);
json j_object(json::value_t::object);
json j_array(json::value_t::array);
json j_string(json::value_t::string);
json j_boolean(json::value_t::boolean);
const json j_null_const(json::value_t::null);
const json j_object_const(json::value_t::object);
const json j_array_const(json::value_t::array);
const json j_string_const(json::value_t::string);
const json j_boolean_const(json::value_t::boolean);
CHECK_THROWS_WITH_AS(j_null.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
CHECK_THROWS_WITH_AS(j_null_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean_const.get<json::binary_t>(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
CHECK_THROWS_WITH_AS(j_null.get_binary(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object.get_binary(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array.get_binary(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string.get_binary(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean.get_binary(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
CHECK_THROWS_WITH_AS(j_null_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is null",
json::type_error&);
CHECK_THROWS_WITH_AS(j_object_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is object",
json::type_error&);
CHECK_THROWS_WITH_AS(j_array_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is array",
json::type_error&);
CHECK_THROWS_WITH_AS(j_string_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is string",
json::type_error&);
CHECK_THROWS_WITH_AS(j_boolean_const.get_binary(),
"[json.exception.type_error.302] type must be binary, but is boolean",
json::type_error&);
}
}
#if JSON_USE_IMPLICIT_CONVERSIONS
SECTION("get a binary value (implicit)")
{
json::binary_t const n_reference{{1, 2, 3}};
json const j(n_reference);
SECTION("binary_t")
{
json::binary_t const b = j;
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
}
#endif
#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION
SECTION("get an enum")
{
enum c_enum { value_1, value_2 }; // NOLINT(cppcoreguidelines-use-enum-class)
enum class cpp_enum { value_1, value_2 };
CHECK(json(value_1).get<c_enum>() == value_1);
CHECK(json(cpp_enum::value_1).get<cpp_enum>() == cpp_enum::value_1);
}
SECTION("get an enum with underlying type bool (#5671)")
{
enum class bool_enum : bool { off, on };
CHECK(json(bool_enum::off).get<bool_enum>() == bool_enum::off);
CHECK(json(bool_enum::on).get<bool_enum>() == bool_enum::on);
}
#endif
SECTION("more involved conversions")
{
SECTION("object-like STL containers")
{
json const j1 = {{"one", 1}, {"two", 2}, {"three", 3}};
json const j2 = {{"one", 1u}, {"two", 2u}, {"three", 3u}};
json const j3 = {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}};
json const j4 = {{"one", true}, {"two", false}, {"three", true}};
json const j5 = {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}};
SECTION("std::map")
{
CHECK(j1.get<std::map<std::string, int>>() == (std::map<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::map<std::string, unsigned int>>() == (std::map<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::map<std::string, double>>() == (std::map<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::map<std::string, bool>>() == (std::map<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
CHECK(j5.get<std::map<std::string, std::string>>() == (std::map<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
}
SECTION("std::unordered_map")
{
CHECK(j1.get<std::unordered_map<std::string, int>>() == (std::unordered_map<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::unordered_map<std::string, unsigned int>>() == (std::unordered_map<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::unordered_map<std::string, double>>() == (std::unordered_map<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::unordered_map<std::string, bool>>() == (std::unordered_map<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
const auto m5 = j5.get<std::unordered_map<std::string, std::string>>();
CHECK(m5 == (std::unordered_map<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
CHECK(m5.at("one") == "eins");
}
SECTION("reserve is called on containers that support it (#5406)")
{
// build a larger object so that a missing/incorrect reserve()
// call would be more likely to corrupt or drop elements
json j_large;
for (int i = 0; i < 100; ++i)
{
j_large[std::to_string(i)] = i;
}
SECTION("std::unordered_map (supports reserve)")
{
const auto m = j_large.get<std::unordered_map<std::string, int>>();
CHECK(m.size() == 100);
for (int i = 0; i < 100; ++i)
{
CHECK(m.at(std::to_string(i)) == i);
}
}
SECTION("std::map (no reserve, fallback path)")
{
const auto m = j_large.get<std::map<std::string, int>>();
CHECK(m.size() == 100);
for (int i = 0; i < 100; ++i)
{
CHECK(m.at(std::to_string(i)) == i);
}
}
}
SECTION("std::multimap")
{
CHECK(j1.get<std::multimap<std::string, int>>() == (std::multimap<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::multimap<std::string, unsigned int>>() == (std::multimap<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::multimap<std::string, double>>() == (std::multimap<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::multimap<std::string, bool>>() == (std::multimap<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
const auto m5 = j5.get<std::multimap<std::string, std::string>>();
CHECK(m5 == (std::multimap<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
CHECK(m5.find("one")->second == "eins");
}
SECTION("std::unordered_multimap")
{
CHECK(j1.get<std::unordered_multimap<std::string, int>>() == (std::unordered_multimap<std::string, int> {{"one", 1}, {"two", 2}, {"three", 3}}));
CHECK(j2.get<std::unordered_multimap<std::string, unsigned int>>() == (std::unordered_multimap<std::string, unsigned int> {{"one", 1u}, {"two", 2u}, {"three", 3u}}));
CHECK(j3.get<std::unordered_multimap<std::string, double>>() == (std::unordered_multimap<std::string, double> {{"one", 1.1}, {"two", 2.2}, {"three", 3.3}}));
CHECK(j4.get<std::unordered_multimap<std::string, bool>>() == (std::unordered_multimap<std::string, bool> {{"one", true}, {"two", false}, {"three", true}}));
const auto m5 = j5.get<std::unordered_multimap<std::string, std::string>>();
CHECK(m5 == (std::unordered_multimap<std::string, std::string> {{"one", "eins"}, {"two", "zwei"}, {"three", "drei"}}));
CHECK(m5.find("one")->second == "eins");
}
SECTION("exception in case of a non-object type")
{
CHECK_THROWS_WITH_AS(
(json().get<std::map<std::string, int>>()),
"[json.exception.type_error.302] type must be object, but is null", json::type_error&);
}
}
SECTION("array-like STL containers")
{
json const j1 = {1, 2, 3, 4};
json const j2 = {1u, 2u, 3u, 4u};
json const j3 = {1.2, 2.3, 3.4, 4.5};
json const j4 = {true, false, true};
json const j5 = {"one", "two", "three"};
SECTION("std::list")
{
CHECK(j1.get<std::list<int>>() == (std::list<int> {1, 2, 3, 4}));
CHECK(j2.get<std::list<unsigned int>>() == (std::list<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::list<double>>() == (std::list<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::list<bool>>() == (std::list<bool> {true, false, true}));
CHECK(j5.get<std::list<std::string>>() == (std::list<std::string> {"one", "two", "three"}));
}
SECTION("std::forward_list")
{
CHECK(j1.get<std::forward_list<int>>() == (std::forward_list<int> {1, 2, 3, 4}));
CHECK(j2.get<std::forward_list<unsigned int>>() == (std::forward_list<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::forward_list<double>>() == (std::forward_list<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::forward_list<bool>>() == (std::forward_list<bool> {true, false, true}));
CHECK(j5.get<std::forward_list<std::string>>() == (std::forward_list<std::string> {"one", "two", "three"}));
}
SECTION("std::array")
{
CHECK(j1.get<std::array<int, 4>>() == (std::array<int, 4> {{1, 2, 3, 4}}));
// only the first 3 elements of j2 are converted, since the target array is smaller
CHECK(j2.get<std::array<unsigned int, 3>>() == (std::array<unsigned int, 3> {{1u, 2u, 3u}}));
CHECK(j3.get<std::array<double, 4>>() == (std::array<double, 4> {{1.2, 2.3, 3.4, 4.5}}));
CHECK(j4.get<std::array<bool, 3>>() == (std::array<bool, 3> {{true, false, true}}));
CHECK(j5.get<std::array<std::string, 3>>() == (std::array<std::string, 3> {{"one", "two", "three"}}));
SECTION("std::array is larger than JSON")
{
std::array<int, 6> arr6 = {{1, 2, 3, 4, 5, 6}};
CHECK_THROWS_WITH_AS(j1.get_to(arr6), "[json.exception.out_of_range.401] "
"array index 4 is out of range", json::out_of_range&);
}
SECTION("std::array is smaller than JSON")
{
std::array<int, 2> arr2 = {{8, 9}};
j1.get_to(arr2);
CHECK(arr2[0] == 1);
CHECK(arr2[1] == 2);
}
}
SECTION("std::valarray")
{
// valarray has no operator== that returns bool, so compare via a vector copy
const auto v1 = j1.get<std::valarray<int>>();
CHECK((std::vector<int>(std::begin(v1), std::end(v1)) == std::vector<int> {1, 2, 3, 4}));
const auto v2 = j2.get<std::valarray<unsigned int>>();
CHECK((std::vector<unsigned int>(std::begin(v2), std::end(v2)) == std::vector<unsigned int> {1u, 2u, 3u, 4u}));
const auto v3 = j3.get<std::valarray<double>>();
CHECK((std::vector<double>(std::begin(v3), std::end(v3)) == std::vector<double> {1.2, 2.3, 3.4, 4.5}));
const auto v4 = j4.get<std::valarray<bool>>();
CHECK((std::vector<bool>(std::begin(v4), std::end(v4)) == std::vector<bool> {true, false, true}));
const auto v5 = j5.get<std::valarray<std::string>>();
CHECK((std::vector<std::string>(std::begin(v5), std::end(v5)) == std::vector<std::string> {"one", "two", "three"}));
}
SECTION("std::vector")
{
CHECK(j1.get<std::vector<int>>() == (std::vector<int> {1, 2, 3, 4}));
CHECK(j2.get<std::vector<unsigned int>>() == (std::vector<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::vector<double>>() == (std::vector<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::vector<bool>>() == (std::vector<bool> {true, false, true}));
CHECK(j5.get<std::vector<std::string>>() == (std::vector<std::string> {"one", "two", "three"}));
}
SECTION("std::deque")
{
CHECK(j1.get<std::deque<int>>() == (std::deque<int> {1, 2, 3, 4}));
CHECK(j2.get<std::deque<unsigned int>>() == (std::deque<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::deque<double>>() == (std::deque<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::deque<bool>>() == (std::deque<bool> {true, false, true}));
CHECK(j5.get<std::deque<std::string>>() == (std::deque<std::string> {"one", "two", "three"}));
}
SECTION("std::set")
{
CHECK(j1.get<std::set<int>>() == (std::set<int> {1, 2, 3, 4}));
CHECK(j2.get<std::set<unsigned int>>() == (std::set<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::set<double>>() == (std::set<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::set<bool>>() == (std::set<bool> {true, false, true}));
CHECK(j5.get<std::set<std::string>>() == (std::set<std::string> {"one", "two", "three"}));
}
SECTION("std::unordered_set")
{
CHECK(j1.get<std::unordered_set<int>>() == (std::unordered_set<int> {1, 2, 3, 4}));
CHECK(j2.get<std::unordered_set<unsigned int>>() == (std::unordered_set<unsigned int> {1u, 2u, 3u, 4u}));
CHECK(j3.get<std::unordered_set<double>>() == (std::unordered_set<double> {1.2, 2.3, 3.4, 4.5}));
CHECK(j4.get<std::unordered_set<bool>>() == (std::unordered_set<bool> {true, false, true}));
CHECK(j5.get<std::unordered_set<std::string>>() == (std::unordered_set<std::string> {"one", "two", "three"}));
}
SECTION("std::map (array of pairs)")
{
const std::map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
json const j6 = m;
auto m2 = j6.get<std::map<int, int>>();
CHECK(m == m2);
json const j7 = {0, 1, 2, 3};
json const j8 = 2;
#if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS((j7.get<std::map<int, int>>()),
"[json.exception.type_error.302] (/0) type must be array, "
"but is number", json::type_error&);
#else
CHECK_THROWS_WITH_AS((j7.get<std::map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
#endif
CHECK_THROWS_WITH_AS((j8.get<std::map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
SECTION("superfluous entries")
{
json const j9 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
m2 = j9.get<std::map<int, int>>();
CHECK(m == m2);
}
}
SECTION("std::unordered_map (array of pairs)")
{
const std::unordered_map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
json const j6 = m;
auto m2 = j6.get<std::unordered_map<int, int>>();
CHECK(m == m2);
json const j7 = {0, 1, 2, 3};
json const j8 = 2;
#if JSON_DIAGNOSTICS
CHECK_THROWS_WITH_AS((j7.get<std::unordered_map<int, int>>()),
"[json.exception.type_error.302] (/0) type must be array, "
"but is number", json::type_error&);
#else
CHECK_THROWS_WITH_AS((j7.get<std::unordered_map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
#endif
CHECK_THROWS_WITH_AS((j8.get<std::unordered_map<int, int>>()),
"[json.exception.type_error.302] type must be array, "
"but is number", json::type_error&);
SECTION("superfluous entries")
{
json const j9{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
m2 = j9.get<std::unordered_map<int, int>>();
CHECK(m == m2);
}
}
SECTION("exception in case of a non-object type")
{
// does type really must be an array? or it rather must not be null?
// that's what I thought when other test like this one broke
CHECK_THROWS_WITH_AS(
(json().get<std::list<int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::vector<int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::vector<json>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::list<json>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::valarray<int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
CHECK_THROWS_WITH_AS(
(json().get<std::map<int, int>>()),
"[json.exception.type_error.302] type must be array, but is null", json::type_error&);
}
}
}
}
enum class cards {kreuz, pik, herz, karo};
// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM(cards,
{
{cards::kreuz, "kreuz"},
{cards::pik, "pik"},
{cards::pik, "puk"}, // second entry for cards::puk; will not be used
{cards::herz, "herz"},
{cards::karo, "karo"}
})
enum TaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class)
{
TS_STOPPED,
TS_RUNNING,
TS_COMPLETED,
TS_INVALID = -1,
};
// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM(TaskState,
{
{TS_INVALID, nullptr},
{TS_STOPPED, "stopped"},
{TS_RUNNING, "running"},
{TS_COMPLETED, "completed"},
})
TEST_CASE("JSON to enum mapping")
{
SECTION("enum class")
{
// enum -> json
CHECK(json(cards::kreuz) == "kreuz");
CHECK(json(cards::pik) == "pik");
CHECK(json(cards::herz) == "herz");
CHECK(json(cards::karo) == "karo");
// json -> enum
CHECK(cards::kreuz == json("kreuz"));
CHECK(cards::pik == json("pik"));
CHECK(cards::herz == json("herz"));
CHECK(cards::karo == json("karo"));
// invalid json -> first enum
CHECK(cards::kreuz == json("what?").get<cards>());
}
SECTION("traditional enum")
{
// enum -> json
CHECK(json(TS_STOPPED) == "stopped");
CHECK(json(TS_RUNNING) == "running");
CHECK(json(TS_COMPLETED) == "completed");
CHECK(json(TS_INVALID) == json());
// json -> enum
CHECK(TS_STOPPED == json("stopped"));
CHECK(TS_RUNNING == json("running"));
CHECK(TS_COMPLETED == json("completed"));
CHECK(TS_INVALID == json());
// invalid json -> first enum
CHECK(TS_INVALID == json("what?").get<TaskState>());
}
}
enum class strict_cards {kreuz, pik, herz, karo, andere}; // andere not included in mapping
// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(strict_cards,
{
{strict_cards::kreuz, "kreuz"},
{strict_cards::pik, "pik"},
{strict_cards::pik, "puk"}, // second entry for cards::pik; will not be used
{strict_cards::herz, "herz"},
{strict_cards::karo, "karo"}
})
enum StrictTaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class)
{
STRICT_TS_STOPPED,
STRICT_TS_RUNNING,
STRICT_TS_COMPLETED,
STRICT_TS_OTHER, // STRICT_TS_OTHER not in mapping
STRICT_TS_INVALID = -1,
};
// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(StrictTaskState,
{
{STRICT_TS_INVALID, nullptr},
{STRICT_TS_STOPPED, "stopped"},
{STRICT_TS_RUNNING, "running"},
{STRICT_TS_COMPLETED, "completed"},
})
// regression test for #5708 item 2: NLOHMANN_JSON_SERIALIZE_ENUM_STRICT must not rely on
// unqualified lookup of a helper name that a user's own namespace may also declare
namespace ns_with_colliding_name
{
// NOLINTNEXTLINE(misc-use-internal-linkage) - used to shadow the library's internal helper name
inline void templated_json_throw(int /*unused*/) {}
enum class colliding_enum { a, b };
// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(colliding_enum,
{
{colliding_enum::a, "a"},
{colliding_enum::b, "b"}
})
} // namespace ns_with_colliding_name
TEST_CASE("NLOHMANN_JSON_SERIALIZE_ENUM_STRICT in a namespace with a colliding name")
{
using ns_with_colliding_name::colliding_enum;
CHECK(json(colliding_enum::a) == "a");
CHECK(colliding_enum::b == json("b"));
json _;
CHECK_THROWS_WITH_AS(_ = json("nope").get<colliding_enum>(), "[json.exception.out_of_range.410] enum value out of range for colliding_enum: \"nope\"", json::out_of_range&);
}
TEST_CASE("Strict JSON to enum mapping")
{
SECTION("enum class")
{
// enum -> json
CHECK(json(strict_cards::kreuz) == "kreuz");
CHECK(json(strict_cards::pik) == "pik");
CHECK(json(strict_cards::herz) == "herz");
CHECK(json(strict_cards::karo) == "karo");
// json -> enum
CHECK(json("kreuz").get<strict_cards>() == strict_cards::kreuz);
CHECK(json("pik").get<strict_cards>() == strict_cards::pik);
CHECK(json("herz").get<strict_cards>() == strict_cards::herz);
CHECK(json("karo").get<strict_cards>() == strict_cards::karo);
// comparison of enum and json
CHECK(strict_cards::kreuz == json("kreuz"));
CHECK(strict_cards::pik == json("pik"));
CHECK(strict_cards::herz == json("herz"));
CHECK(strict_cards::karo == json("karo"));
// invalid json -> exception thrown
json _;
CHECK_THROWS_WITH_AS(_ = json("what?").get<strict_cards>(), "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"what?\"", json::out_of_range&);
// conversion of unmapped enum -> exception thrown
CHECK_THROWS_WITH_AS(json(strict_cards::andere), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&);
// comparing an unmapped enum with json throws the same exception
// (the scalar comparison operators used to be noexcept, so this
// called std::terminate)
CHECK_THROWS_WITH_AS(static_cast<void>(strict_cards::andere == json("andere")), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&);
CHECK_THROWS_WITH_AS(static_cast<void>(json("andere") != strict_cards::andere), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&);
// invalid UTF-8 -> out_of_range.410, not the type_error.316 thrown while building the
// message (regression test for #5667); such strings can reach get<Enum>() unvalidated,
// e.g. from from_cbor()/from_msgpack() (#5529)
const json j_invalid_utf8 = "\xFF";
CHECK_THROWS_WITH_AS(_ = j_invalid_utf8.get<strict_cards>(), "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"\xEF\xBF\xBD\"", json::out_of_range&);
}
SECTION("traditional enum")
{
// enum -> json
CHECK(json(STRICT_TS_STOPPED) == "stopped");
CHECK(json(STRICT_TS_RUNNING) == "running");
CHECK(json(STRICT_TS_COMPLETED) == "completed");
CHECK(json(STRICT_TS_INVALID) == json());
// json -> enum
CHECK(json("stopped").get<StrictTaskState>() == STRICT_TS_STOPPED);
CHECK(json("running").get<StrictTaskState>() == STRICT_TS_RUNNING);
CHECK(json("completed").get<StrictTaskState>() == STRICT_TS_COMPLETED);
CHECK(json().get<StrictTaskState>() == STRICT_TS_INVALID);
// comparison of enum and json
CHECK(STRICT_TS_STOPPED == json("stopped"));
CHECK(STRICT_TS_RUNNING == json("running"));
CHECK(STRICT_TS_COMPLETED == json("completed"));
CHECK(STRICT_TS_INVALID == json());
// invalid json -> exception thrown
json _;
CHECK_THROWS_WITH_AS(_ = json("what?").get<StrictTaskState>(), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState: \"what?\"", json::out_of_range&);
// conversion of unmapped enum -> exception thrown
CHECK_THROWS_WITH_AS(json(STRICT_TS_OTHER), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState", json::out_of_range&);
// comparing an unmapped enum with json throws the same exception
CHECK_THROWS_WITH_AS(static_cast<void>(STRICT_TS_OTHER < json("x")), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState", json::out_of_range&);
}
}
#ifdef JSON_HAS_CPP_17
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
TEST_CASE("std::filesystem::path")
{
SECTION("ascii")
{
json const j_string = "Path";
auto p = j_string.template get<nlohmann::detail::std_fs::path>();
json const j_path = p;
CHECK(j_path.template get<std::string>() ==
j_string.template get<std::string>());
}
SECTION("utf-8")
{
json const j_string = "P\xc4\x9b\xc5\xa1ina";
auto p = j_string.template get<nlohmann::detail::std_fs::path>();
json const j_path = p;
CHECK(j_path.template get<std::string>() ==
j_string.template get<std::string>());
}
}
#endif
// the ADL to_json overload for std::u8string only exists under the same guard
// as std::filesystem::path support (it is otherwise only reached indirectly,
// via std::filesystem::path::u8string()) -- mirror both #if conditions from
// include/nlohmann/detail/conversions/to_json.hpp exactly
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
#if defined(__cpp_lib_char8_t)
TEST_CASE("std::u8string")
{
SECTION("ascii")
{
const std::u8string s = u8"Path";
json const j = s;
CHECK(j.template get<std::string>() == "Path");
}
SECTION("utf-8")
{
// use \u universal-character-names (rather than raw \x byte escapes
// or literal non-ASCII source bytes) to compose the multi-byte UTF-8
// encoding -- MSVC treats \x escapes used that way inside a u8
// literal as a nonstandard extension (warning C5321), which some of
// our CI configs promote to an error; \u is portable and produces
// the exact same encoded bytes without depending on the source
// file's encoding
const std::u8string s = u8"P\u011B\u0161ina";
json const j = s;
CHECK(j.template get<std::string>() == "P\xc4\x9b\xc5\xa1ina");
}
}
#endif
#endif
#if !defined(JSON_NOEXCEPTION)
namespace
{
// a type whose to_json reports an error by throwing, used below to check that
// converting a std::optional<T> to JSON propagates an exception thrown while
// converting its contained value instead of calling std::terminate (#5642)
struct throwing_to_json_type {};
[[noreturn]] void to_json(json& /*unused*/, const throwing_to_json_type& /*unused*/)
{
throw std::runtime_error("cannot serialize throwing_to_json_type");
}
} // namespace
#endif
TEST_CASE("std::optional")
{
SECTION("null")
{
const json j_null;
const std::optional<std::string> opt_null;
CHECK(json(opt_null) == j_null);
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&);
// Assignment goes through the same overload resolution as direct
// construction, so it throws for the same reason. This relies on
// basic_json's implicit conversion operator, so it only applies
// when JSON_USE_IMPLICIT_CONVERSIONS is enabled (the default).
#if JSON_USE_IMPLICIT_CONVERSIONS
std::optional<std::string> opt_assign;
CHECK_THROWS_WITH_AS(opt_assign = j_null,
"[json.exception.type_error.302] type must be string, but is null", json::type_error&);
#endif
// get_to() is the correct way to obtain std::nullopt from a JSON null.
std::optional<std::string> opt_get_to = "placeholder";
j_null.get_to(opt_get_to);
CHECK(opt_get_to == std::nullopt);
}
SECTION("string")
{
json j_string = "string";
std::optional<std::string> opt_string = "string";
CHECK(json(opt_string) == j_string);
CHECK(std::optional<std::string>(j_string) == opt_string);
// false positive: Infer attributes the destruction of the temporaries above to opt_string
// @infer-ignore USE_AFTER_DELETE
}
SECTION("bool")
{
json j_bool = true;
std::optional<bool> opt_bool = true;
CHECK(json(opt_bool) == j_bool);
CHECK(std::optional<bool>(j_bool) == opt_bool);
}
SECTION("number")
{
json j_number = 1;
std::optional<int> opt_int = 1;
CHECK(json(opt_int) == j_number);
CHECK(j_number.get<std::optional<int>>() == opt_int);
}
SECTION("array")
{
json j_array = {1, 2, nullptr};
std::vector<std::optional<int>> opt_array = {{1, 2, std::nullopt}};
CHECK(json(opt_array) == j_array);
CHECK(j_array.get<std::vector<std::optional<int>>>() == opt_array);
}
SECTION("object")
{
json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}};
std::map<std::string, std::optional<int>> opt_object {{"one", 1}, {"two", 2}, {"zero", std::nullopt}};
CHECK(json(opt_object) == j_object);
CHECK(std::map<std::string, std::optional<int>>(j_object) == opt_object);
}
#if !defined(JSON_NOEXCEPTION)
SECTION("exception from contained value's to_json propagates (#5642)")
{
// to_json(BasicJsonType&, const std::optional<T>&) must not be
// noexcept: it calls T's to_json, which may throw (a user-defined
// to_json that reports an error, or std::bad_alloc for T =
// std::string/vector/json). Before the fix, this called
// std::terminate() instead of letting the exception propagate.
const std::optional<throwing_to_json_type> opt = throwing_to_json_type{};
CHECK_THROWS_WITH_AS(json(opt), "cannot serialize throwing_to_json_type", std::runtime_error&);
// the conversion is noexcept exactly when converting the contained value is
static_assert(!std::is_nothrow_constructible<json, const std::optional<throwing_to_json_type>&>::value);
static_assert(std::is_nothrow_constructible<json, const std::optional<int>&>::value);
}
#endif
}
#endif
#ifdef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_17
#endif
#ifdef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_14
#endif
DOCTEST_CLANG_SUPPRESS_WARNING_POP
+1 -1
View File
@@ -505,7 +505,7 @@ static json_with_const_base make_nested_array(std::size_t depth)
{ {
if (depth == 0) if (depth == 0)
{ {
return json_with_const_base(1); return json_with_const_base(1); // NOLINT(modernize-return-braced-init-list): {1} would be an array
} }
return json_with_const_base::array({make_nested_array(depth - 1)}); return json_with_const_base::array({make_nested_array(depth - 1)});
} }
@@ -1,214 +0,0 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
// This file tests the opt-in JSON_DELETE_DEPRECATED_FUNCTIONS, so it defines the
// macro itself instead of relying on the build configuration.
#ifdef JSON_DELETE_DEPRECATED_FUNCTIONS
#undef JSON_DELETE_DEPRECATED_FUNCTIONS
#endif
#define JSON_DELETE_DEPRECATED_FUNCTIONS 1
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <cstddef>
#include <cstdint>
#include <istream>
#include <ostream>
#include <string>
#include <type_traits>
#include <utility>
namespace
{
template<typename...>
struct make_void
{
using type = void;
};
template<typename... Ts>
using void_t = typename make_void<Ts...>::type;
// A deleted function is still found by overload resolution, but naming it in an
// unevaluated operand is ill-formed, so each of the following traits is false
// exactly if the expression selects a deleted (or no) function.
#define JSON_TEST_DETECT(name, expr) \
template<typename J, typename = void> \
struct name : std::false_type {}; \
template<typename J> \
struct name<J, void_t<decltype(expr)>> : std::true_type {}
using ptr_t = const std::uint8_t*;
JSON_TEST_DETECT(from_cbor_ptr_len, J::from_cbor(std::declval<ptr_t>(), std::declval<std::size_t>()));
JSON_TEST_DETECT(from_msgpack_ptr_len, J::from_msgpack(std::declval<ptr_t>(), std::declval<std::size_t>()));
JSON_TEST_DETECT(from_ubjson_ptr_len, J::from_ubjson(std::declval<ptr_t>(), std::declval<std::size_t>()));
JSON_TEST_DETECT(from_bjdata_ptr_len, J::from_bjdata(std::declval<ptr_t>(), std::declval<std::size_t>()));
JSON_TEST_DETECT(from_bon8_ptr_len, J::from_bon8(std::declval<ptr_t>(), std::declval<std::size_t>()));
JSON_TEST_DETECT(from_bson_ptr_len, J::from_bson(std::declval<ptr_t>(), std::declval<std::size_t>()));
JSON_TEST_DETECT(from_cbor_ptr_ptr, J::from_cbor(std::declval<ptr_t>(), std::declval<ptr_t>()));
JSON_TEST_DETECT(from_msgpack_ptr_ptr, J::from_msgpack(std::declval<ptr_t>(), std::declval<ptr_t>()));
JSON_TEST_DETECT(from_ubjson_ptr_ptr, J::from_ubjson(std::declval<ptr_t>(), std::declval<ptr_t>()));
JSON_TEST_DETECT(from_bjdata_ptr_ptr, J::from_bjdata(std::declval<ptr_t>(), std::declval<ptr_t>()));
JSON_TEST_DETECT(from_bon8_ptr_ptr, J::from_bon8(std::declval<ptr_t>(), std::declval<ptr_t>()));
JSON_TEST_DETECT(from_bson_ptr_ptr, J::from_bson(std::declval<ptr_t>(), std::declval<ptr_t>()));
JSON_TEST_DETECT(from_cbor_init_list, J::from_cbor({std::declval<ptr_t>(), std::declval<std::size_t>()}));
JSON_TEST_DETECT(from_msgpack_init_list, J::from_msgpack({std::declval<ptr_t>(), std::declval<std::size_t>()}));
JSON_TEST_DETECT(from_ubjson_init_list, J::from_ubjson({std::declval<ptr_t>(), std::declval<std::size_t>()}));
JSON_TEST_DETECT(from_bson_init_list, J::from_bson({std::declval<ptr_t>(), std::declval<std::size_t>()}));
JSON_TEST_DETECT(parse_init_list, J::parse({std::declval<ptr_t>(), std::declval<std::size_t>()}));
JSON_TEST_DETECT(accept_init_list, J::accept({std::declval<ptr_t>(), std::declval<std::size_t>()}));
JSON_TEST_DETECT(sax_parse_init_list, J::sax_parse({std::declval<ptr_t>(), std::declval<std::size_t>()}, std::declval<nlohmann::json_sax<J>*>()));
JSON_TEST_DETECT(parse_ptr_ptr, J::parse(std::declval<ptr_t>(), std::declval<ptr_t>()));
JSON_TEST_DETECT(iterator_wrapper, J::iterator_wrapper(std::declval<J&>()));
JSON_TEST_DETECT(iterator_wrapper_const, J::iterator_wrapper(std::declval<const J&>()));
JSON_TEST_DETECT(items, std::declval<J&>().items());
JSON_TEST_DETECT(json_ltlt_istream, std::declval<J&>() << std::declval<std::istream&>());
JSON_TEST_DETECT(istream_gtgt_json, std::declval<std::istream&>() >> std::declval<J&>());
JSON_TEST_DETECT(json_gtgt_ostream, std::declval<const J&>() >> std::declval<std::ostream&>());
JSON_TEST_DETECT(ostream_ltlt_json, std::declval<std::ostream&>() << std::declval<const J&>());
JSON_TEST_DETECT(ptr_eq_ptr, std::declval<const typename J::json_pointer&>() == std::declval<const typename J::json_pointer&>());
JSON_TEST_DETECT(ptr_ne_ptr, std::declval<const typename J::json_pointer&>() != std::declval<const typename J::json_pointer&>());
JSON_TEST_DETECT(ptr_eq_string, std::declval<const typename J::json_pointer&>() == std::declval<const std::string&>());
JSON_TEST_DETECT(string_eq_ptr, std::declval<const std::string&>() == std::declval<const typename J::json_pointer&>());
JSON_TEST_DETECT(ptr_eq_c_string, std::declval<const typename J::json_pointer&>() == std::declval<const char*>());
JSON_TEST_DETECT(c_string_eq_ptr, std::declval<const char*>() == std::declval<const typename J::json_pointer&>());
JSON_TEST_DETECT(ptr_ne_string, std::declval<const typename J::json_pointer&>() != std::declval<const std::string&>());
JSON_TEST_DETECT(string_ne_ptr, std::declval<const std::string&>() != std::declval<const typename J::json_pointer&>());
JSON_TEST_DETECT(ptr_to_string, std::declval<const typename J::json_pointer&>().to_string());
// json_pointer with a basic_json type as template argument
template<typename J>
using legacy_ptr_t = const nlohmann::json_pointer<J>& ;
JSON_TEST_DETECT(legacy_ptr_value, std::declval<const J&>().value(std::declval<legacy_ptr_t<J>>(), 0));
JSON_TEST_DETECT(legacy_ptr_value_rvalue, std::declval<const J&>().value(std::declval<legacy_ptr_t<J>>(), std::string()));
JSON_TEST_DETECT(legacy_ptr_contains, std::declval<const J&>().contains(std::declval<legacy_ptr_t<J>>()));
JSON_TEST_DETECT(legacy_ptr_subscript, std::declval<J&>()[std::declval<legacy_ptr_t<J>>()]);
JSON_TEST_DETECT(legacy_ptr_subscript_const, std::declval<const J&>()[std::declval<legacy_ptr_t<J>>()]);
JSON_TEST_DETECT(legacy_ptr_at, std::declval<J&>().at(std::declval<legacy_ptr_t<J>>()));
JSON_TEST_DETECT(legacy_ptr_at_const, std::declval<const J&>().at(std::declval<legacy_ptr_t<J>>()));
JSON_TEST_DETECT(ptr_value, std::declval<const J&>().value(std::declval<const typename J::json_pointer&>(), 0));
JSON_TEST_DETECT(ptr_at, std::declval<J&>().at(std::declval<const typename J::json_pointer&>()));
#undef JSON_TEST_DETECT
} // namespace
TEST_CASE("JSON_DELETE_DEPRECATED_FUNCTIONS")
{
SECTION("from_* with a pointer and a length")
{
// the overloads are deleted rather than removed, so the length cannot
// silently bind to the strict parameter of from_*(InputType&&, bool)
CHECK_FALSE(from_cbor_ptr_len<json>::value);
CHECK_FALSE(from_msgpack_ptr_len<json>::value);
CHECK_FALSE(from_ubjson_ptr_len<json>::value);
CHECK_FALSE(from_bjdata_ptr_len<json>::value);
CHECK_FALSE(from_bon8_ptr_len<json>::value);
CHECK_FALSE(from_bson_ptr_len<json>::value);
// the replacement
CHECK(from_cbor_ptr_ptr<json>::value);
CHECK(from_msgpack_ptr_ptr<json>::value);
CHECK(from_ubjson_ptr_ptr<json>::value);
CHECK(from_bjdata_ptr_ptr<json>::value);
CHECK(from_bon8_ptr_ptr<json>::value);
CHECK(from_bson_ptr_ptr<json>::value);
}
SECTION("initializer lists of a pointer and a length")
{
CHECK_FALSE(from_cbor_init_list<json>::value);
CHECK_FALSE(from_msgpack_init_list<json>::value);
CHECK_FALSE(from_ubjson_init_list<json>::value);
CHECK_FALSE(from_bson_init_list<json>::value);
CHECK_FALSE(parse_init_list<json>::value);
CHECK_FALSE(accept_init_list<json>::value);
CHECK_FALSE(sax_parse_init_list<json>::value);
// the replacement
CHECK(parse_ptr_ptr<json>::value);
}
SECTION("iterator_wrapper")
{
CHECK_FALSE(iterator_wrapper<json>::value);
CHECK_FALSE(iterator_wrapper_const<json>::value);
// the replacement
CHECK(items<json>::value);
}
SECTION("stream operators with reversed operands")
{
CHECK_FALSE(json_ltlt_istream<json>::value);
CHECK_FALSE(json_gtgt_ostream<json>::value);
// the replacement
CHECK(istream_gtgt_json<json>::value);
CHECK(ostream_ltlt_json<json>::value);
}
SECTION("json_pointer")
{
// conversion to a string
CHECK_FALSE(std::is_constructible<std::string, json::json_pointer>::value);
CHECK_FALSE(std::is_convertible<json::json_pointer, std::string>::value);
// comparison with a string
CHECK_FALSE(ptr_eq_string<json>::value);
CHECK_FALSE(string_eq_ptr<json>::value);
CHECK_FALSE(ptr_eq_c_string<json>::value);
CHECK_FALSE(c_string_eq_ptr<json>::value);
CHECK_FALSE(ptr_ne_string<json>::value);
CHECK_FALSE(string_ne_ptr<json>::value);
// the replacement
CHECK(ptr_to_string<json>::value);
CHECK(ptr_eq_ptr<json>::value);
CHECK(ptr_ne_ptr<json>::value);
}
SECTION("json_pointer with a basic_json type as template argument")
{
CHECK_FALSE(legacy_ptr_value<json>::value);
CHECK_FALSE(legacy_ptr_value_rvalue<json>::value);
CHECK_FALSE(legacy_ptr_contains<json>::value);
CHECK_FALSE(legacy_ptr_subscript<json>::value);
CHECK_FALSE(legacy_ptr_subscript_const<json>::value);
CHECK_FALSE(legacy_ptr_at<json>::value);
CHECK_FALSE(legacy_ptr_at_const<json>::value);
// the replacement
CHECK(ptr_value<json>::value);
CHECK(ptr_at<json>::value);
}
SECTION("the non-deprecated functions still work")
{
const json j = {{"a", {1, 2}}};
const auto cbor = json::to_cbor(j);
CHECK(json::from_cbor(cbor.data(), cbor.data() + cbor.size()) == j);
const json::json_pointer ptr("/a/1");
CHECK(ptr == json::json_pointer("/a/1"));
CHECK(ptr.to_string() == "/a/1");
CHECK(j[ptr] == 2);
CHECK(j.at(ptr) == 2);
CHECK(j.value(ptr, 0) == 2);
CHECK(j.contains(ptr));
}
}
+2 -14
View File
@@ -16,14 +16,6 @@
#define JSON_TEST_STRICT_NUL_HANDLING_ENABLED 1 #define JSON_TEST_STRICT_NUL_HANDLING_ENABLED 1
#endif #endif
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
#ifdef JSON_TEST_NO_GLOBAL_UDLS #ifdef JSON_TEST_NO_GLOBAL_UDLS
@@ -299,7 +291,6 @@ TEST_CASE("deserialization")
})); }));
} }
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
SECTION("operator<<") SECTION("operator<<")
{ {
std::stringstream ss; std::stringstream ss;
@@ -308,7 +299,6 @@ TEST_CASE("deserialization")
j << ss; j << ss;
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
} }
#endif
SECTION("operator>>") SECTION("operator>>")
{ {
@@ -433,7 +423,6 @@ TEST_CASE("deserialization")
CHECK_THROWS_WITH_AS(_ = json::parse(nullptr), "[json.exception.parse_error.101] parse error: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&); CHECK_THROWS_WITH_AS(_ = json::parse(nullptr), "[json.exception.parse_error.101] parse error: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
} }
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
SECTION("operator<<") SECTION("operator<<")
{ {
std::stringstream ss; std::stringstream ss;
@@ -441,7 +430,6 @@ TEST_CASE("deserialization")
json j; json j;
CHECK_THROWS_WITH_AS(j << ss, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&); CHECK_THROWS_WITH_AS(j << ss, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
} }
#endif
SECTION("operator>>") SECTION("operator>>")
{ {
@@ -1160,9 +1148,9 @@ TEST_CASE("deserialization")
{ {
std::istringstream s(bom + "123 456"); std::istringstream s(bom + "123 456");
json j; json j;
s >> j; j << s;
CHECK(j == 123); CHECK(j == 123);
s >> j; j << s;
CHECK(j == 456); CHECK(j == 456);
} }
} }
+3
View File
@@ -14,6 +14,9 @@ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using json = nlohmann::json; using json = nlohmann::json;
#ifdef JSON_TEST_NO_GLOBAL_UDLS
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
#endif
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// for #2824 // for #2824
+7 -2
View File
@@ -1963,8 +1963,8 @@ TEST_CASE("operator[] with user-defined std::string_view-convertible types")
}; };
json j = {{"foo", "from_class"}, {"bar", "from_struct"}}; json j = {{"foo", "from_class"}, {"bar", "from_struct"}};
TestClass foo_obj; const TestClass foo_obj;
TestStruct bar_obj; const TestStruct bar_obj;
SECTION("read access") SECTION("read access")
{ {
@@ -2005,6 +2005,10 @@ TEST_CASE("keys convertible to std::string_view work with all lookup functions (
// 3.12.0, such a key worked with at, the const operator[], find, count and // 3.12.0, such a key worked with at, the const operator[], find, count and
// contains via the conversion to std::string; #4958 made the KeyType&& // contains via the conversion to std::string; #4958 made the KeyType&&
// templates win overload resolution for it instead, and those then failed // templates win overload resolution for it instead, and those then failed
// the lookups pick the conversion to std::string_view, which leaves the one
// to std::string unused; it has to exist to reproduce the ambiguity
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
struct DualKey struct DualKey
{ {
operator std::string() const operator std::string() const
@@ -2016,6 +2020,7 @@ TEST_CASE("keys convertible to std::string_view work with all lookup functions (
return "a"; return "a";
} }
}; };
DOCTEST_CLANG_SUPPRESS_WARNING_POP
SECTION("nlohmann::json") SECTION("nlohmann::json")
{ {
-10
View File
@@ -8,14 +8,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -27,7 +19,6 @@ DOCTEST_GCC_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wrange-loop-construct") DOCTEST_CLANG_SUPPRESS_WARNING("-Wrange-loop-construct")
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
TEST_CASE("iterator_wrapper") TEST_CASE("iterator_wrapper")
{ {
SECTION("object") SECTION("object")
@@ -724,7 +715,6 @@ TEST_CASE("iterator_wrapper")
} }
} }
} }
#endif
TEST_CASE("items()") TEST_CASE("items()")
{ {
+4 -19
View File
@@ -9,14 +9,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
#define JSON_TESTS_PRIVATE #define JSON_TESTS_PRIVATE
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
#ifdef JSON_TEST_NO_GLOBAL_UDLS #ifdef JSON_TEST_NO_GLOBAL_UDLS
@@ -572,9 +564,7 @@ TEST_CASE("JSON pointers")
std::stringstream ss; std::stringstream ss;
ss << ptr; ss << ptr;
CHECK(ptr.to_string() == ptr_str); CHECK(ptr.to_string() == ptr_str);
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
CHECK(std::string(ptr) == ptr_str); CHECK(std::string(ptr) == ptr_str);
#endif
CHECK(ss.str() == ptr_str); CHECK(ss.str() == ptr_str);
} }
} }
@@ -754,6 +744,8 @@ TEST_CASE("JSON pointers")
SECTION("equality comparison") SECTION("equality comparison")
{ {
const char* ptr_cpstring = "/foo/bar";
const char ptr_castring[] = "/foo/bar"; // NOLINT(misc-const-correctness,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
std::string ptr_string{"/foo/bar"}; std::string ptr_string{"/foo/bar"};
auto ptr1 = json::json_pointer(ptr_string); auto ptr1 = json::json_pointer(ptr_string);
auto ptr2 = json::json_pointer(ptr_string); auto ptr2 = json::json_pointer(ptr_string);
@@ -763,12 +755,6 @@ TEST_CASE("JSON pointers")
CHECK(ptr1 == ptr2); CHECK(ptr1 == ptr2);
CHECK_FALSE(ptr1 != ptr2);
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
const char* ptr_cpstring = "/foo/bar";
const char ptr_castring[] = "/foo/bar"; // NOLINT(misc-const-correctness,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
CHECK(ptr1 == "/foo/bar"); CHECK(ptr1 == "/foo/bar");
CHECK(ptr1 == ptr_cpstring); CHECK(ptr1 == ptr_cpstring);
CHECK(ptr1 == ptr_castring); CHECK(ptr1 == ptr_castring);
@@ -779,6 +765,8 @@ TEST_CASE("JSON pointers")
CHECK(ptr_castring == ptr1); CHECK(ptr_castring == ptr1);
CHECK(ptr_string == ptr1); CHECK(ptr_string == ptr1);
CHECK_FALSE(ptr1 != ptr2);
CHECK_FALSE(ptr1 != "/foo/bar"); CHECK_FALSE(ptr1 != "/foo/bar");
CHECK_FALSE(ptr1 != ptr_cpstring); CHECK_FALSE(ptr1 != ptr_cpstring);
CHECK_FALSE(ptr1 != ptr_castring); CHECK_FALSE(ptr1 != ptr_castring);
@@ -800,7 +788,6 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_WITH_AS("/~~" == ptr1, CHECK_THROWS_WITH_AS("/~~" == ptr1,
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&); "[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&);
} }
#endif
} }
SECTION("less-than comparison") SECTION("less-than comparison")
@@ -852,7 +839,6 @@ TEST_CASE("JSON pointers")
json_ptr_j ptr_j{ptr_string}; json_ptr_j ptr_j{ptr_string};
json_ptr_oj ptr_oj{ptr_string}; json_ptr_oj ptr_oj{ptr_string};
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
CHECK(j.contains(ptr)); CHECK(j.contains(ptr));
CHECK(j.contains(ptr_j)); CHECK(j.contains(ptr_j));
CHECK(j.contains(ptr_oj)); CHECK(j.contains(ptr_oj));
@@ -865,7 +851,6 @@ TEST_CASE("JSON pointers")
CHECK(j.value(ptr, "x") == j.value(ptr_j, "x")); CHECK(j.value(ptr, "x") == j.value(ptr_j, "x"));
CHECK(j.value(ptr, "x") == j.value(ptr_oj, "x")); CHECK(j.value(ptr, "x") == j.value(ptr_oj, "x"));
#endif
CHECK(ptr == ptr_j); CHECK(ptr == ptr_j);
CHECK(ptr == ptr_oj); CHECK(ptr == ptr_oj);
+2
View File
@@ -1162,6 +1162,7 @@ TEST_CASE("update() on deeply nested values")
TEST_CASE("update() with an argument that aliases *this (#5641)") TEST_CASE("update() with an argument that aliases *this (#5641)")
{ {
#if !defined(JSON_NOEXCEPTION) // checks which exception is thrown, and that nothing changed
SECTION("the target is checked before the argument, as before the copy") SECTION("the target is checked before the argument, as before the copy")
{ {
json j = 1; json j = 1;
@@ -1172,6 +1173,7 @@ TEST_CASE("update() with an argument that aliases *this (#5641)")
CHECK_THROWS_WITH_AS(k.update(json::array()), "[json.exception.type_error.312] cannot use update() with array", json::type_error&); CHECK_THROWS_WITH_AS(k.update(json::array()), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
CHECK(k == json::object()); CHECK(k == json::object());
} }
#endif
SECTION("const reference") SECTION("const reference")
{ {
+1 -13
View File
@@ -8,14 +8,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
#ifdef JSON_TEST_NO_GLOBAL_UDLS #ifdef JSON_TEST_NO_GLOBAL_UDLS
@@ -1568,7 +1560,7 @@ TEST_CASE("MessagePack")
// dump() still requires valid UTF-8 and throws for such a value, // dump() still requires valid UTF-8 and throws for such a value,
// unless an error handler that replaces or ignores the bytes is // unless an error handler that replaces or ignores the bytes is
// passed // passed
CHECK_THROWS_AS(j_value.dump(), json::type_error&); CHECK_THROWS_AS(utils::ignore_return_value(j_value.dump()), json::type_error&);
// the same bytes as an object key round-trip as well // the same bytes as an object key round-trip as well
const std::vector<uint8_t> ill_formed_key = {0x81, 0xa2, 0xc0, 0xae, 0x01}; const std::vector<uint8_t> ill_formed_key = {0x81, 0xa2, 0xc0, 0xae, 0x01};
@@ -1803,10 +1795,8 @@ TEST_CASE("MessagePack input that cannot be read is discarded by every overload"
CHECK_THROWS_AS(_ = json::from_msgpack(input.begin(), input.end()), json::parse_error&); CHECK_THROWS_AS(_ = json::from_msgpack(input.begin(), input.end()), json::parse_error&);
CHECK(json::from_msgpack(input, true, false).is_discarded()); CHECK(json::from_msgpack(input, true, false).is_discarded());
CHECK(json::from_msgpack(input.begin(), input.end(), true, false).is_discarded()); CHECK(json::from_msgpack(input.begin(), input.end(), true, false).is_discarded());
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
CHECK(json::from_msgpack(input.data(), input.size(), true, false).is_discarded()); CHECK(json::from_msgpack(input.data(), input.size(), true, false).is_discarded());
CHECK(json::from_msgpack({input.data(), input.size()}, true, false).is_discarded()); CHECK(json::from_msgpack({input.data(), input.size()}, true, false).is_discarded());
#endif
} }
TEST_CASE("MessagePack SAX parsing stops at every event") TEST_CASE("MessagePack SAX parsing stops at every event")
@@ -2109,14 +2099,12 @@ TEST_CASE("MessagePack roundtrips" * doctest::skip())
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
{ {
INFO_WITH_TEMP(filename + ": uint8_t* and size"); INFO_WITH_TEMP(filename + ": uint8_t* and size");
json j2; json j2;
CHECK_NOTHROW(j2 = json::from_msgpack({packed.data(), packed.size()})); CHECK_NOTHROW(j2 = json::from_msgpack({packed.data(), packed.size()}));
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#endif
{ {
INFO_WITH_TEMP(filename + ": output to output adapters"); INFO_WITH_TEMP(filename + ": output to output adapters");
+3 -3
View File
@@ -430,8 +430,8 @@ TEST_CASE("ordered_map")
SECTION("with T& (lvalue)") SECTION("with T& (lvalue)")
{ {
std::string one = "1"; std::string one = "1"; // NOLINT(misc-const-correctness): emplace must accept a non-const lvalue
std::string four = "four"; std::string four = "four"; // NOLINT(misc-const-correctness): see above
auto res1 = om.emplace("eins", one); auto res1 = om.emplace("eins", one);
CHECK(res1.first == om.begin()); CHECK(res1.first == om.begin());
@@ -467,7 +467,7 @@ TEST_CASE("ordered_map")
SECTION("with key of key_type (non-template overload)") SECTION("with key of key_type (non-template overload)")
{ {
const std::string key_vier{"vier"}; const std::string key_vier{"vier"};
std::string four = "four"; std::string four = "four"; // NOLINT(misc-const-correctness): emplace must accept a non-const lvalue
auto res4 = om.emplace(key_vier, four); auto res4 = om.emplace(key_vier, four);
CHECK(res4.first == om.begin() + 3); CHECK(res4.first == om.begin() + 3);
+1 -1
View File
@@ -569,7 +569,7 @@ TEST_CASE("regression tests 2")
SECTION("issue #2067 - cannot serialize binary data to text JSON") SECTION("issue #2067 - cannot serialize binary data to text JSON")
{ {
const std::array<unsigned char, 23> data = {{0x81, 0xA4, 0x64, 0x61, 0x74, 0x61, 0xC4, 0x0F, 0x33, 0x30, 0x30, 0x32, 0x33, 0x34, 0x30, 0x31, 0x30, 0x37, 0x30, 0x35, 0x30, 0x31, 0x30}}; const std::array<unsigned char, 23> data = {{0x81, 0xA4, 0x64, 0x61, 0x74, 0x61, 0xC4, 0x0F, 0x33, 0x30, 0x30, 0x32, 0x33, 0x34, 0x30, 0x31, 0x30, 0x37, 0x30, 0x35, 0x30, 0x31, 0x30}};
const json j = json::from_msgpack(data.begin(), data.end()); const json j = json::from_msgpack(data.data(), data.size());
// dump() is nodiscard; this only checks that dumping does not throw // dump() is nodiscard; this only checks that dumping does not throw
CHECK_NOTHROW( CHECK_NOTHROW(
utils::ignore_return_value( utils::ignore_return_value(
-10
View File
@@ -8,14 +8,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -56,7 +48,6 @@ TEST_CASE("serialization")
} }
} }
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
SECTION("operator>>") SECTION("operator>>")
{ {
SECTION("no given width") SECTION("no given width")
@@ -88,7 +79,6 @@ TEST_CASE("serialization")
"[\n\t\"foo\",\n\t1,\n\t2,\n\t3,\n\tfalse,\n\t{\n\t\t\"one\": 1\n\t}\n]"); "[\n\t\"foo\",\n\t1,\n\t2,\n\t3,\n\tfalse,\n\t{\n\t\t\"one\": 1\n\t}\n]");
} }
} }
#endif
SECTION("dump") SECTION("dump")
{ {
+1 -13
View File
@@ -8,14 +8,6 @@
#include "doctest_compatibility.h" #include "doctest_compatibility.h"
// capture whether JSON_DELETE_DEPRECATED_FUNCTIONS was enabled on the command
// line *before* including json.hpp, since the library #undefs it once the header
// has been fully processed (see include/nlohmann/detail/macro_unscope.hpp); the
// tests of deprecated functions are skipped if these functions are deleted
#if defined(JSON_DELETE_DEPRECATED_FUNCTIONS) && (JSON_DELETE_DEPRECATED_FUNCTIONS == 1)
#define JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
#endif
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
@@ -2220,10 +2212,8 @@ TEST_CASE("UBJSON input that cannot be read is discarded by every overload")
CHECK_THROWS_AS(_ = json::from_ubjson(input.begin(), input.end()), json::parse_error&); CHECK_THROWS_AS(_ = json::from_ubjson(input.begin(), input.end()), json::parse_error&);
CHECK(json::from_ubjson(input, true, false).is_discarded()); CHECK(json::from_ubjson(input, true, false).is_discarded());
CHECK(json::from_ubjson(input.begin(), input.end(), true, false).is_discarded()); CHECK(json::from_ubjson(input.begin(), input.end(), true, false).is_discarded());
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
CHECK(json::from_ubjson(input.data(), input.size(), true, false).is_discarded()); CHECK(json::from_ubjson(input.data(), input.size(), true, false).is_discarded());
CHECK(json::from_ubjson({input.data(), input.size()}, true, false).is_discarded()); CHECK(json::from_ubjson({input.data(), input.size()}, true, false).is_discarded());
#endif
} }
TEST_CASE("UBJSON SAX parsing stops at every event") TEST_CASE("UBJSON SAX parsing stops at every event")
@@ -2530,7 +2520,7 @@ TEST_CASE("Universal Binary JSON Specification Examples 1")
CHECK_NOTHROW(j = json::from_ubjson(v)); CHECK_NOTHROW(j = json::from_ubjson(v));
REQUIRE(j.is_string()); REQUIRE(j.is_string());
CHECK(j.get_ref<const json::string_t&>() == std::string("\xc0\xae")); CHECK(j.get_ref<const json::string_t&>() == std::string("\xc0\xae"));
CHECK_THROWS_AS(j.dump(), json::type_error&); CHECK_THROWS_AS(utils::ignore_return_value(j.dump()), json::type_error&);
CHECK(json::from_ubjson(json::to_ubjson(j)) == j); CHECK(json::from_ubjson(json::to_ubjson(j)) == j);
// the same bytes as an object key round-trip as well // the same bytes as an object key round-trip as well
@@ -2971,14 +2961,12 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip())
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#ifndef JSON_TEST_DEPRECATED_FUNCTIONS_DELETED
{ {
INFO_WITH_TEMP(filename + ": uint8_t* and size"); INFO_WITH_TEMP(filename + ": uint8_t* and size");
json j2; json j2;
CHECK_NOTHROW(j2 = json::from_ubjson({packed.data(), packed.size()})); CHECK_NOTHROW(j2 = json::from_ubjson({packed.data(), packed.size()}));
CHECK(j1 == j2); CHECK(j1 == j2);
} }
#endif
{ {
INFO_WITH_TEMP(filename + ": output to output adapters"); INFO_WITH_TEMP(filename + ": output to output adapters");
+2 -2
View File
@@ -37,10 +37,10 @@ TEST_CASE("wide strings")
// 32-bit wchar_t first encodes it as an ill-formed three-byte // 32-bit wchar_t first encodes it as an ill-formed three-byte
// sequence (rejected one byte later, at column 3) // sequence (rejected one byte later, at column 3)
const char* const error_low_surrogate = sizeof(wchar_t) == 2 const char* const error_low_surrogate = sizeof(wchar_t) == 2
? "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"<U+0000>'" ? "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\xFF'"
: "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\xED\xB0'"; : "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\xED\xB0'";
const char* const error_high_surrogate = sizeof(wchar_t) == 2 const char* const error_high_surrogate = sizeof(wchar_t) == 2
? "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"<U+0000>'" ? "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\xFF'"
: "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\xED\xA0'"; : "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\xED\xA0'";
// a lone low surrogate cannot start a pair // a lone low surrogate cannot start a pair