mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 04:00:31 +00:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c65caa5bf | ||
|
|
6a073dbae4 | ||
|
|
fdcc569eee | ||
|
|
38528b4a38 | ||
|
|
9cbe62efb0 | ||
|
|
471c7678cf | ||
|
|
4fabfb27f7 | ||
|
|
71b4eaf743 | ||
|
|
2790175d79 | ||
|
|
cc9fafa0e1 | ||
|
|
8d6d1264a7 | ||
|
|
d75f9ab161 | ||
|
|
c3774be4e2 | ||
|
|
91365ca3b2 | ||
|
|
605cc6c81d | ||
|
|
f012b85d06 | ||
|
|
243b6e20e3 | ||
|
|
0a0d5623be | ||
|
|
22c9ce3f21 | ||
|
|
0d2240ad1e |
@@ -31,6 +31,45 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --target ci_test_gcc
|
run: cmake --build build --target ci_test_gcc
|
||||||
|
|
||||||
|
ci_meson_install:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Get latest CMake and ninja
|
||||||
|
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||||
|
- name: Install Meson
|
||||||
|
run: pip install meson
|
||||||
|
- name: Install with Meson
|
||||||
|
run: |
|
||||||
|
meson setup build-meson --prefix=${{ github.workspace }}/install
|
||||||
|
meson install -C build-meson
|
||||||
|
- name: Use the installed package with find_package
|
||||||
|
run: |
|
||||||
|
cmake -S tests/cmake_import/project -B build-import -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install
|
||||||
|
cmake --build build-import
|
||||||
|
- name: Install with Meson and non-default options
|
||||||
|
run: |
|
||||||
|
meson setup build-meson-options --prefix=${{ github.workspace }}/install-options -DMultipleHeaders=true -DDiagnostics=true -DGlobalUDLs=false
|
||||||
|
meson install -C build-meson-options
|
||||||
|
- name: Check that the options reach the installed files
|
||||||
|
run: |
|
||||||
|
test -d install-options/include/nlohmann/detail
|
||||||
|
cflags=$(PKG_CONFIG_PATH=${{ github.workspace }}/install-options/share/pkgconfig pkg-config --cflags nlohmann_json)
|
||||||
|
echo "$cflags"
|
||||||
|
echo "$cflags" | grep -q -- '-DJSON_DIAGNOSTICS=1'
|
||||||
|
echo "$cflags" | grep -q -- '-DJSON_USE_GLOBAL_UDLS=0'
|
||||||
|
grep -q 'JSON_USE_GLOBAL_UDLS=0;JSON_DIAGNOSTICS=1' install-options/share/cmake/nlohmann_json/nlohmann_jsonTargets.cmake
|
||||||
|
cmake -S tests/cmake_import/project -B build-import-options -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install-options
|
||||||
|
cmake --build build-import-options
|
||||||
|
- name: Install with Meson and the include directory outside the prefix
|
||||||
|
run: |
|
||||||
|
meson setup build-meson-split --prefix=${{ github.workspace }}/install-split --includedir=${{ github.workspace }}/install-split-dev/include
|
||||||
|
meson install -C build-meson-split
|
||||||
|
cmake -S tests/cmake_import/project -B build-import-split -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install-split
|
||||||
|
cmake --build build-import-split
|
||||||
|
|
||||||
ci_infer:
|
ci_infer:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
+24
-1
@@ -168,7 +168,30 @@ if (MSVC)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Install a pkg-config file, so other tools can find this.
|
# Install a pkg-config file, so other tools can find this. It carries the same
|
||||||
|
# compile definitions as the target above.
|
||||||
|
set(NLOHMANN_JSON_PKGCONFIG_CFLAGS "")
|
||||||
|
if (NOT JSON_GlobalUDLs)
|
||||||
|
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_GLOBAL_UDLS=0")
|
||||||
|
endif()
|
||||||
|
if (NOT JSON_ImplicitConversions)
|
||||||
|
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_IMPLICIT_CONVERSIONS=0")
|
||||||
|
endif()
|
||||||
|
if (JSON_DisableEnumSerialization)
|
||||||
|
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DISABLE_ENUM_SERIALIZATION=1")
|
||||||
|
endif()
|
||||||
|
if (JSON_Diagnostics)
|
||||||
|
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DIAGNOSTICS=1")
|
||||||
|
endif()
|
||||||
|
if (JSON_Diagnostic_Positions)
|
||||||
|
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_DIAGNOSTIC_POSITIONS=1")
|
||||||
|
endif()
|
||||||
|
if (JSON_LegacyDiscardedValueComparison)
|
||||||
|
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1")
|
||||||
|
endif()
|
||||||
|
if (JSON_StrictNulHandling)
|
||||||
|
string(APPEND NLOHMANN_JSON_PKGCONFIG_CFLAGS " -DJSON_STRICT_NUL_HANDLING=1")
|
||||||
|
endif()
|
||||||
configure_file(
|
configure_file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in"
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||||
|
|||||||
@@ -260,9 +260,29 @@ make BUILD.bazel
|
|||||||
|
|
||||||
The "Check amalgamation" workflow fails if the file is out of date.
|
The "Check amalgamation" workflow fails if the file is out of date.
|
||||||
|
|
||||||
### `meson.build`
|
### `meson.build` and `meson_options.txt`
|
||||||
|
|
||||||
The build definition for the [Meson](https://mesonbuild.com) build system.
|
Meson build definitions suitable for use as a subproject ("wrap" in Meson terminology).
|
||||||
|
|
||||||
|
Projects wishing to use the wrap can execute:
|
||||||
|
```sh
|
||||||
|
meson wrap install nlohmann_json
|
||||||
|
```
|
||||||
|
|
||||||
|
Which allows Meson to build from source when a system provided dependency isn't available.
|
||||||
|
|
||||||
|
To build directly:
|
||||||
|
```sh
|
||||||
|
meson setup builddir
|
||||||
|
ninja -C builddir
|
||||||
|
```
|
||||||
|
|
||||||
|
`meson_options.txt` defines the options, which mirror the CMake options that change the library's target (for example,
|
||||||
|
`-DDiagnostics=true`). Meson requires this file next to `meson.build`, so it is also part of `include.zip`.
|
||||||
|
|
||||||
|
When installing, `meson.build` installs the headers, a pkg-config file, and the CMake package config files, so that
|
||||||
|
`find_package(nlohmann_json)` works. As Meson cannot generate `nlohmann_jsonTargets.cmake` itself, it is created from
|
||||||
|
the template `cmake/nlohmann_jsonTargets.cmake.in`, which is only used by Meson.
|
||||||
|
|
||||||
### `Package.swift`
|
### `Package.swift`
|
||||||
|
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ json.tar.xz:
|
|||||||
# We use `-X` to make the resulting ZIP file reproducible, see
|
# We use `-X` to make the resulting ZIP file reproducible, see
|
||||||
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
|
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
|
||||||
include.zip: BUILD.bazel
|
include.zip: BUILD.bazel
|
||||||
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
|
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build meson_options.txt LICENSE.MIT
|
||||||
|
|
||||||
# Create the files for a release and add signatures and hashes.
|
# Create the files for a release and add signatures and hashes.
|
||||||
release: include.zip json.tar.xz
|
release: include.zip json.tar.xz
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Imported target for installations made with Meson (see meson.build).
|
||||||
|
#
|
||||||
|
# CMake installations generate this file with install(EXPORT ...). Meson cannot
|
||||||
|
# do that, but as the library is header-only, the target only needs an include
|
||||||
|
# directory, the C++ standard, and the compile definitions of the options that
|
||||||
|
# differ from their defaults. Paths are computed relative to this file so that
|
||||||
|
# the installation can be relocated (e.g., into a sysroot), unless includedir or
|
||||||
|
# datadir is outside the prefix.
|
||||||
|
|
||||||
|
if(TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_CONFIG_TO_PREFIX@" ABSOLUTE)
|
||||||
|
|
||||||
|
add_library(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ INTERFACE IMPORTED)
|
||||||
|
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "@NLOHMANN_JSON_INCLUDE_DIR@"
|
||||||
|
)
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.8)
|
||||||
|
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||||
|
INTERFACE_COMPILE_FEATURES cxx_range_for
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||||
|
INTERFACE_COMPILE_FEATURES cxx_std_11
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_NLOHMANN_JSON_COMPILE_DEFINITIONS "@NLOHMANN_JSON_COMPILE_DEFINITIONS@")
|
||||||
|
if(_NLOHMANN_JSON_COMPILE_DEFINITIONS)
|
||||||
|
set_target_properties(@PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES
|
||||||
|
INTERFACE_COMPILE_DEFINITIONS "${_NLOHMANN_JSON_COMPILE_DEFINITIONS}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(_NLOHMANN_JSON_COMPILE_DEFINITIONS)
|
||||||
|
unset(_IMPORT_PREFIX)
|
||||||
@@ -4,4 +4,4 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
|||||||
Name: @PROJECT_NAME@
|
Name: @PROJECT_NAME@
|
||||||
Description: JSON for Modern C++
|
Description: JSON for Modern C++
|
||||||
Version: @PROJECT_VERSION@
|
Version: @PROJECT_VERSION@
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}@NLOHMANN_JSON_PKGCONFIG_CFLAGS@
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ By default, `#!cpp JSON_NO_AUTOMATIC_UDLS` is not defined, and `<nlohmann/json.h
|
|||||||
- [`operator""_json`](../operator_literal_json.md)
|
- [`operator""_json`](../operator_literal_json.md)
|
||||||
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
||||||
- [`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
- [`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
||||||
- [Compile times](../../integration/compile_times.md) - options to reduce compile times
|
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ Deserializes an input stream to a JSON value.
|
|||||||
|
|
||||||
the stream `i`
|
the stream `i`
|
||||||
|
|
||||||
|
## Exception safety
|
||||||
|
|
||||||
|
Strong guarantee: if an exception is thrown, there are no changes in `j`.
|
||||||
|
|
||||||
## Exceptions
|
## Exceptions
|
||||||
|
|
||||||
- Throws [`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token, or if
|
- Throws [`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token, or if
|
||||||
@@ -125,3 +129,5 @@ being read.
|
|||||||
the stream; planned to become the default in version 4.0.0.
|
the stream; planned to become the default in version 4.0.0.
|
||||||
- Fixed a null pointer dereference for an `std::istream` without a stream buffer (now throws `parse_error.101`), and a
|
- Fixed a null pointer dereference for an `std::istream` without a stream buffer (now throws `parse_error.101`), and a
|
||||||
crash (`std::terminate`) when `i` has `eofbit` in its exception mask, in version 3.13.0.
|
crash (`std::terminate`) when `i` has `eofbit` in its exception mask, in version 3.13.0.
|
||||||
|
- Changed to the strong exception safety guarantee in version 3.13.0: `j` is no longer left with a partially parsed
|
||||||
|
value if parsing throws.
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
|||||||
| Functionality | Additional requirement |
|
| Functionality | Additional requirement |
|
||||||
|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| [`diff`](../../api/basic_json/diff.md), [`items`](../../api/basic_json/items.md), [`std::hash`](../../api/basic_json/std_hash.md) | conversion of a `#!cpp std::size_t` to `StringType`: either assignability from the result of `#!cpp std::to_string`, or an ADL overload `#!cpp void int_to_string(StringType&, std::size_t)` |
|
| [`diff`](../../api/basic_json/diff.md), [`items`](../../api/basic_json/items.md), [`std::hash`](../../api/basic_json/std_hash.md) | conversion of a `#!cpp std::size_t` to `StringType`: either assignability from the result of `#!cpp std::to_string`, or an ADL overload `#!cpp void int_to_string(StringType&, std::size_t)` |
|
||||||
|
| [`operator/(std::size_t)`](../../api/json_pointer/operator_slash.md) | the same conversion of a `#!cpp std::size_t` to `StringType` as `diff`, `items`, and `std::hash` above |
|
||||||
| [`std::hash<basic_json>`](../../api/basic_json/std_hash.md) | additionally a specialization of `#!cpp std::hash<StringType>` |
|
| [`std::hash<basic_json>`](../../api/basic_json/std_hash.md) | additionally a specialization of `#!cpp std::hash<StringType>` |
|
||||||
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
|
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
|
||||||
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
|
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
# Compile times
|
|
||||||
|
|
||||||
The library is header-only and makes heavy use of templates, so every translation unit that includes
|
|
||||||
`<nlohmann/json.hpp>` pays for parsing the header and instantiating what it uses. This page lists the options to reduce
|
|
||||||
that cost, ordered by how much they typically save.
|
|
||||||
|
|
||||||
!!! info "Measurements"
|
|
||||||
|
|
||||||
The numbers below are medians of nine runs compiling a single translation unit with `-std=c++17 -c` against the
|
|
||||||
single-header version, with Apple clang and GCC 16 on macOS (Apple silicon). They show the order of magnitude to
|
|
||||||
expect; measure your own code before and after a change.
|
|
||||||
|
|
||||||
## Include `json_fwd.hpp` in headers
|
|
||||||
|
|
||||||
Header files that only need to *name* the `json` type — for function declarations, members held by pointer or
|
|
||||||
reference, or friend declarations — can include `<nlohmann/json_fwd.hpp>` instead of `<nlohmann/json.hpp>`. It only
|
|
||||||
forward-declares `basic_json`, `json`, `ordered_json`, `json_pointer`, and `adl_serializer`. The translation units that
|
|
||||||
actually use the values then include `<nlohmann/json.hpp>`.
|
|
||||||
|
|
||||||
```cpp title="person.hpp"
|
|
||||||
#pragma once
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
|
||||||
|
|
||||||
struct person;
|
|
||||||
void to_json(nlohmann::json& j, const person& p);
|
|
||||||
void from_json(const nlohmann::json& j, person& p);
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp title="person.cpp"
|
|
||||||
#include "person.hpp"
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
void to_json(nlohmann::json& j, const person& p) { /* ... */ }
|
|
||||||
void from_json(const nlohmann::json& j, person& p) { /* ... */ }
|
|
||||||
```
|
|
||||||
|
|
||||||
| Compiler | `json.hpp` (`-O0`) | `json_fwd.hpp` (`-O0`) | Change |
|
|
||||||
|-------------|-------------------:|-----------------------:|-------:|
|
|
||||||
| Apple clang | 704 ms | 329 ms | −53% |
|
|
||||||
| GCC 16 | 779 ms | 242 ms | −69% |
|
|
||||||
|
|
||||||
This is the most effective option, because it avoids the full header in every translation unit that includes
|
|
||||||
*your* headers.
|
|
||||||
|
|
||||||
## Opt out of the automatic user-defined string literals
|
|
||||||
|
|
||||||
The user-defined string literals [`operator""_json`](../api/operator_literal_json.md) and
|
|
||||||
[`operator""_json_pointer`](../api/operator_literal_json_pointer.md) are ordinary inline functions whose bodies call the
|
|
||||||
parser. As `<nlohmann/json.hpp>` includes them by default, every translation unit instantiates the parser, even if it
|
|
||||||
never parses anything itself.
|
|
||||||
|
|
||||||
Define [`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md) for the whole project and include
|
|
||||||
`<nlohmann/json_literals.hpp>` only in the files that use the literals:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
target_compile_definitions(my_target PRIVATE JSON_NO_AUTOMATIC_UDLS)
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <nlohmann/json_literals.hpp> // only where "..."_json is used
|
|
||||||
```
|
|
||||||
|
|
||||||
The saving applies to translation units that do not parse JSON, for example ones that define types and their
|
|
||||||
conversions or only pass `json` values around:
|
|
||||||
|
|
||||||
| Compiler | Translation unit | Default (`-O0` / `-O2`) | `JSON_NO_AUTOMATIC_UDLS` (`-O0` / `-O2`) | Change |
|
|
||||||
|-------------|------------------|------------------------:|-----------------------------------------:|------------:|
|
|
||||||
| Apple clang | model | 776 ms / 846 ms | 629 ms / 692 ms | −19% / −18% |
|
|
||||||
| GCC 16 | model | 1022 ms / 1120 ms | 882 ms / 965 ms | −14% / −14% |
|
|
||||||
| Apple clang | parsing | 992 ms / 1815 ms | 1006 ms / 1823 ms | +1% / 0% |
|
|
||||||
| GCC 16 | parsing | 2018 ms / 3420 ms | 1990 ms / 3454 ms | −1% / +1% |
|
|
||||||
|
|
||||||
Translation units that include only the header save up to a third. Translation units that parse anyway instantiate
|
|
||||||
the parser regardless and see no difference.
|
|
||||||
|
|
||||||
## Instantiate `basic_json` once
|
|
||||||
|
|
||||||
Each translation unit instantiates the member functions of `nlohmann::json` it uses. An explicit instantiation
|
|
||||||
declaration tells the compiler that the non-template members are instantiated elsewhere, so it can skip them:
|
|
||||||
|
|
||||||
```cpp title="json_instance.hpp"
|
|
||||||
#pragma once
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
extern template class nlohmann::basic_json<>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp title="json_instance.cpp"
|
|
||||||
#include "json_instance.hpp"
|
|
||||||
|
|
||||||
template class nlohmann::basic_json<>;
|
|
||||||
```
|
|
||||||
|
|
||||||
Include `json_instance.hpp` instead of `<nlohmann/json.hpp>` and compile and link `json_instance.cpp` once.
|
|
||||||
|
|
||||||
| Compiler | Translation unit | Default (`-O0` / `-O2`) | `extern template` (`-O0` / `-O2`) | Change |
|
|
||||||
|-------------|---------------------|------------------------:|----------------------------------:|------------:|
|
|
||||||
| Apple clang | parsing | 992 ms / 1815 ms | 953 ms / 1625 ms | −4% / −10% |
|
|
||||||
| GCC 16 | parsing | 2018 ms / 3420 ms | 1522 ms / 2728 ms | −25% / −20% |
|
|
||||||
| Apple clang | `json_instance.cpp` | — | 2166 ms / 4660 ms | — |
|
|
||||||
| GCC 16 | `json_instance.cpp` | — | 5085 ms / 10616 ms | — |
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- The saving grows with the number of translation units that use `json`, while the instantiation translation unit is
|
|
||||||
compiled only once (and is rarely recompiled, as it does not depend on your code).
|
|
||||||
- Member function templates (such as `get<T>()`, `parse(InputType&&)`, or `value(key, default)`) are not covered by
|
|
||||||
the explicit instantiation and are still instantiated where they are used.
|
|
||||||
- The declaration covers exactly `nlohmann::json`. Add the same lines for `nlohmann::ordered_json`
|
|
||||||
(`nlohmann::basic_json<nlohmann::ordered_map>`) or your own `basic_json` specializations if you use them.
|
|
||||||
|
|
||||||
## Use C++20 modules
|
|
||||||
|
|
||||||
With a toolchain that supports named modules, `import nlohmann.json;` compiles the library once into a module and
|
|
||||||
avoids parsing the header in every translation unit. See [Modules](../features/modules.md) for requirements and known
|
|
||||||
issues. Module support is experimental and currently depends heavily on the compiler version.
|
|
||||||
|
|
||||||
## Use precompiled headers
|
|
||||||
|
|
||||||
Build systems can precompile `<nlohmann/json.hpp>` together with other stable headers, for example with CMake's
|
|
||||||
[`target_precompile_headers`](https://cmake.org/cmake/help/latest/command/target_precompile_headers.html):
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
target_precompile_headers(my_target PRIVATE <nlohmann/json.hpp>)
|
|
||||||
```
|
|
||||||
|
|
||||||
This removes the cost of parsing the header, but not of instantiating templates in each translation unit, so it
|
|
||||||
combines well with the options above.
|
|
||||||
|
|
||||||
## Options without effect on compile times
|
|
||||||
|
|
||||||
Some configuration macros change what the library declares, but do not measurably change compile times:
|
|
||||||
|
|
||||||
| Macro | Apple clang, model (`-O0` / `-O2`) | GCC 16, model (`-O0` / `-O2`) |
|
|
||||||
|------------------------------------------------------------------------|-----------------------------------:|------------------------------:|
|
|
||||||
| default | 776 ms / 846 ms | 1022 ms / 1120 ms |
|
|
||||||
| [`JSON_NO_IO`](../api/macros/json_no_io.md) | 764 ms / 836 ms | 1022 ms / 1117 ms |
|
|
||||||
| [`JSON_USE_GLOBAL_UDLS`](../api/macros/json_use_global_udls.md)`=0` | 763 ms / 852 ms | 1019 ms / 1106 ms |
|
|
||||||
|
|
||||||
`JSON_USE_GLOBAL_UDLS` only controls *where* the literals are declared; to avoid their cost, use
|
|
||||||
`JSON_NO_AUTOMATIC_UDLS` instead.
|
|
||||||
|
|
||||||
## See also
|
|
||||||
|
|
||||||
- [`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md) - do not include the user-defined string
|
|
||||||
literals automatically
|
|
||||||
- [Modules](../features/modules.md) - C++20 module support
|
|
||||||
- [Header only](index.md) - including the library
|
|
||||||
@@ -15,7 +15,7 @@ Clang).
|
|||||||
|
|
||||||
You can further use file
|
You can further use file
|
||||||
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
|
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
|
||||||
for forward declarations (see [Compile times](compile_times.md)), and file
|
for forward declarations, and file
|
||||||
[`single_include/nlohmann/json_literals.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_literals.hpp)
|
[`single_include/nlohmann/json_literals.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_literals.hpp)
|
||||||
for the user-defined string literals if you define
|
for the user-defined string literals if you define
|
||||||
[`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md).
|
[`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md).
|
||||||
|
|||||||
@@ -121,10 +121,23 @@ meson wrap install nlohmann_json
|
|||||||
Please see the Meson project for any issues regarding the packaging.
|
Please see the Meson project for any issues regarding the packaging.
|
||||||
|
|
||||||
The provided `meson.build` can also be used as an alternative to CMake for installing `nlohmann_json` system-wide in
|
The provided `meson.build` can also be used as an alternative to CMake for installing `nlohmann_json` system-wide in
|
||||||
which case a pkg-config file is installed. To use it, have your build system require the `nlohmann_json`
|
which case a pkg-config file and the CMake package config files are installed. To use it, have your build system require
|
||||||
pkg-config dependency. In Meson, it is preferred to use the
|
the `nlohmann_json` pkg-config dependency, or use [`find_package(nlohmann_json)`](cmake.md#external) in CMake. In Meson,
|
||||||
[`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than
|
it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a
|
||||||
using the subproject directly.
|
subproject fallback, rather than using the subproject directly.
|
||||||
|
|
||||||
|
The options that change the library's configuration are available in Meson as well, named like the
|
||||||
|
[CMake options](cmake.md#cmake-options) without the `JSON_` prefix: `MultipleHeaders`, `GlobalUDLs`,
|
||||||
|
`ImplicitConversions`, `DisableEnumSerialization`, `Diagnostics`, `Diagnostic_Positions`,
|
||||||
|
`LegacyDiscardedValueComparison`, and `StrictNulHandling`. They have the same defaults as in CMake, except that
|
||||||
|
`MultipleHeaders` is `false`. Set them with `-D` when setting up the build, or with the subproject name as prefix when
|
||||||
|
the library is used as a subproject:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
meson setup build -Dnlohmann_json:Diagnostics=true
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting compile definitions are part of the Meson dependency, the pkg-config file, and the CMake target.
|
||||||
|
|
||||||
??? example "Example: Wrap"
|
??? example "Example: Wrap"
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ nav:
|
|||||||
- integration/cmake.md
|
- integration/cmake.md
|
||||||
- integration/package_managers.md
|
- integration/package_managers.md
|
||||||
- integration/pkg-config.md
|
- integration/pkg-config.md
|
||||||
- integration/compile_times.md
|
|
||||||
- API Documentation:
|
- API Documentation:
|
||||||
- basic_json:
|
- basic_json:
|
||||||
- 'Overview': api/basic_json/index.md
|
- 'Overview': api/basic_json/index.md
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/string_concat.hpp>
|
#include <nlohmann/detail/string_concat.hpp>
|
||||||
#include <nlohmann/detail/string_escape.hpp>
|
#include <nlohmann/detail/string_escape.hpp>
|
||||||
|
#include <nlohmann/detail/string_utils.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
@@ -116,7 +117,7 @@ class json_pointer
|
|||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
||||||
json_pointer& operator/=(std::size_t array_idx)
|
json_pointer& operator/=(std::size_t array_idx)
|
||||||
{
|
{
|
||||||
return *this /= std::to_string(array_idx);
|
return *this /= detail::to_string<string_t>(array_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
||||||
@@ -752,7 +753,7 @@ class json_pointer
|
|||||||
// would throw out_of_range.404 -- contains() must not throw (see #5395)
|
// would throw out_of_range.404 -- contains() must not throw (see #5395)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
|
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !('0' <= reference_token[0] && reference_token[0] <= '9')))
|
||||||
{
|
{
|
||||||
// invalid char
|
// invalid char
|
||||||
return false;
|
return false;
|
||||||
@@ -780,7 +781,7 @@ class json_pointer
|
|||||||
// not throw (see #5395), so such a reference token is treated as "not found"
|
// not throw (see #5395), so such a reference token is treated as "not found"
|
||||||
errno = 0; // strtoull() does not reset errno on success
|
errno = 0; // strtoull() does not reset errno on success
|
||||||
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||||
const unsigned long long magnitude = std::strtoull(reference_token.c_str(), &p_end, 10); // NOLINT(runtime/int)
|
const unsigned long long magnitude = std::strtoull(reference_token.data(), &p_end, 10); // NOLINT(runtime/int)
|
||||||
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
||||||
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5092,7 +5092,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
|
||||||
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
||||||
{
|
{
|
||||||
parser(detail::input_adapter(i)).parse(false, j);
|
// parse into a temporary so that j is left unchanged if parsing fails
|
||||||
|
basic_json result;
|
||||||
|
parser(detail::input_adapter(i)).parse(false, result);
|
||||||
|
j = std::move(result);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|||||||
+96
-9
@@ -2,24 +2,111 @@ project('nlohmann_json',
|
|||||||
'cpp',
|
'cpp',
|
||||||
version : '3.12.0',
|
version : '3.12.0',
|
||||||
license : 'MIT',
|
license : 'MIT',
|
||||||
|
meson_version : '>= 0.64',
|
||||||
|
default_options: ['cpp_std=c++11'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if get_option('MultipleHeaders')
|
||||||
|
incdir = 'include'
|
||||||
|
else
|
||||||
|
incdir = 'single_include'
|
||||||
|
endif
|
||||||
|
|
||||||
|
# The same compile definitions as the CMake target (see target_compile_definitions
|
||||||
|
# in CMakeLists.txt): only an option that differs from its default adds one.
|
||||||
|
json_defines = []
|
||||||
|
if not get_option('GlobalUDLs')
|
||||||
|
json_defines += 'JSON_USE_GLOBAL_UDLS=0'
|
||||||
|
endif
|
||||||
|
if not get_option('ImplicitConversions')
|
||||||
|
json_defines += 'JSON_USE_IMPLICIT_CONVERSIONS=0'
|
||||||
|
endif
|
||||||
|
if get_option('DisableEnumSerialization')
|
||||||
|
json_defines += 'JSON_DISABLE_ENUM_SERIALIZATION=1'
|
||||||
|
endif
|
||||||
|
if get_option('Diagnostics')
|
||||||
|
json_defines += 'JSON_DIAGNOSTICS=1'
|
||||||
|
endif
|
||||||
|
if get_option('Diagnostic_Positions')
|
||||||
|
json_defines += 'JSON_DIAGNOSTIC_POSITIONS=1'
|
||||||
|
endif
|
||||||
|
if get_option('LegacyDiscardedValueComparison')
|
||||||
|
json_defines += 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1'
|
||||||
|
endif
|
||||||
|
if get_option('StrictNulHandling')
|
||||||
|
json_defines += 'JSON_STRICT_NUL_HANDLING=1'
|
||||||
|
endif
|
||||||
|
|
||||||
|
cpp_args = []
|
||||||
|
foreach define : json_defines
|
||||||
|
cpp_args += '-D' + define
|
||||||
|
endforeach
|
||||||
|
|
||||||
nlohmann_json_dep = declare_dependency(
|
nlohmann_json_dep = declare_dependency(
|
||||||
include_directories: include_directories('single_include')
|
compile_args: cpp_args,
|
||||||
|
include_directories: include_directories(incdir)
|
||||||
)
|
)
|
||||||
|
meson.override_dependency('nlohmann_json', nlohmann_json_dep)
|
||||||
|
|
||||||
|
# The multi-header version under the name earlier versions of this file used
|
||||||
nlohmann_json_multiple_headers = declare_dependency(
|
nlohmann_json_multiple_headers = declare_dependency(
|
||||||
|
compile_args: cpp_args,
|
||||||
include_directories: include_directories('include')
|
include_directories: include_directories('include')
|
||||||
)
|
)
|
||||||
|
|
||||||
if not meson.is_subproject()
|
if not meson.is_subproject()
|
||||||
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
|
install_subdir(
|
||||||
install_headers('single_include/nlohmann/json_fwd.hpp', subdir: 'nlohmann')
|
incdir / 'nlohmann',
|
||||||
install_headers('single_include/nlohmann/json_literals.hpp', subdir: 'nlohmann')
|
install_dir: get_option('includedir'),
|
||||||
|
install_tag: 'devel',
|
||||||
|
)
|
||||||
|
|
||||||
pkgc = import('pkgconfig')
|
pkgc = import('pkgconfig')
|
||||||
pkgc.generate(name: 'nlohmann_json',
|
pkgc.generate(name: 'nlohmann_json',
|
||||||
version: meson.project_version(),
|
version: meson.project_version(),
|
||||||
description: 'JSON for Modern C++'
|
description: 'JSON for Modern C++',
|
||||||
)
|
extra_cflags: cpp_args,
|
||||||
|
install_dir: get_option('datadir') / 'pkgconfig',
|
||||||
|
)
|
||||||
|
|
||||||
|
# CMake package config files, so that find_package(nlohmann_json) works. The
|
||||||
|
# include directory is given relative to the config files, so that the
|
||||||
|
# installation can be relocated. This is not possible if includedir or datadir
|
||||||
|
# is an absolute path outside the prefix (e.g., with the separate outputs of
|
||||||
|
# Nix); then the absolute include directory is used, as CMake does.
|
||||||
|
fs = import('fs')
|
||||||
|
cmake_install_dir = get_option('datadir') / 'cmake' / meson.project_name()
|
||||||
|
cmake_to_prefix = []
|
||||||
|
if fs.is_absolute(get_option('includedir')) or fs.is_absolute(cmake_install_dir)
|
||||||
|
cmake_include_dir = (get_option('prefix') / get_option('includedir')).replace('\\', '/')
|
||||||
|
else
|
||||||
|
foreach component : cmake_install_dir.split('/')
|
||||||
|
cmake_to_prefix += '..'
|
||||||
|
endforeach
|
||||||
|
cmake_include_dir = '${_IMPORT_PREFIX}/' + get_option('includedir')
|
||||||
|
endif
|
||||||
|
|
||||||
|
cmake_conf = configuration_data()
|
||||||
|
cmake_conf.set('PROJECT_NAME', meson.project_name())
|
||||||
|
cmake_conf.set('PROJECT_VERSION', meson.project_version())
|
||||||
|
cmake_conf.set('PROJECT_VERSION_MAJOR', meson.project_version().split('.')[0])
|
||||||
|
cmake_conf.set('NLOHMANN_JSON_TARGET_NAME', meson.project_name())
|
||||||
|
cmake_conf.set('NLOHMANN_JSON_TARGETS_EXPORT_NAME', meson.project_name() + 'Targets')
|
||||||
|
cmake_conf.set('NLOHMANN_JSON_INCLUDE_DIR', cmake_include_dir)
|
||||||
|
cmake_conf.set('NLOHMANN_JSON_CONFIG_TO_PREFIX', '/'.join(cmake_to_prefix))
|
||||||
|
cmake_conf.set('NLOHMANN_JSON_COMPILE_DEFINITIONS', ';'.join(json_defines))
|
||||||
|
|
||||||
|
foreach cmake_file : [
|
||||||
|
['cmake/config.cmake.in', 'nlohmann_jsonConfig.cmake'],
|
||||||
|
['cmake/nlohmann_jsonConfigVersion.cmake.in', 'nlohmann_jsonConfigVersion.cmake'],
|
||||||
|
['cmake/nlohmann_jsonTargets.cmake.in', 'nlohmann_jsonTargets.cmake'],
|
||||||
|
]
|
||||||
|
configure_file(
|
||||||
|
input: cmake_file[0],
|
||||||
|
output: cmake_file[1],
|
||||||
|
configuration: cmake_conf,
|
||||||
|
format: 'cmake@',
|
||||||
|
install_dir: cmake_install_dir,
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
option(
|
||||||
|
'MultipleHeaders',
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
description: 'Use non-amalgamated version of the library',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
'GlobalUDLs',
|
||||||
|
type: 'boolean',
|
||||||
|
value: true,
|
||||||
|
description: 'Place user-defined string literals in the global namespace',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
'ImplicitConversions',
|
||||||
|
type: 'boolean',
|
||||||
|
value: true,
|
||||||
|
description: 'Enable implicit conversions',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
'DisableEnumSerialization',
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
description: 'Disable default integer enum serialization',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
'Diagnostics',
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
description: 'Use extended diagnostic messages',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
'Diagnostic_Positions',
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
description: 'Enable diagnostic positions',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
'LegacyDiscardedValueComparison',
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
description: 'Enable legacy discarded value comparison',
|
||||||
|
)
|
||||||
|
option(
|
||||||
|
'StrictNulHandling',
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
description: 'Enable strict NUL-byte handling',
|
||||||
|
)
|
||||||
@@ -19636,6 +19636,8 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
// #include <nlohmann/detail/string_escape.hpp>
|
// #include <nlohmann/detail/string_escape.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/string_utils.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/value_t.hpp>
|
// #include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
|
|
||||||
@@ -19727,7 +19729,7 @@ class json_pointer
|
|||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
||||||
json_pointer& operator/=(std::size_t array_idx)
|
json_pointer& operator/=(std::size_t array_idx)
|
||||||
{
|
{
|
||||||
return *this /= std::to_string(array_idx);
|
return *this /= detail::to_string<string_t>(array_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
||||||
@@ -20363,7 +20365,7 @@ class json_pointer
|
|||||||
// would throw out_of_range.404 -- contains() must not throw (see #5395)
|
// would throw out_of_range.404 -- contains() must not throw (see #5395)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
|
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !('0' <= reference_token[0] && reference_token[0] <= '9')))
|
||||||
{
|
{
|
||||||
// invalid char
|
// invalid char
|
||||||
return false;
|
return false;
|
||||||
@@ -20391,7 +20393,7 @@ class json_pointer
|
|||||||
// not throw (see #5395), so such a reference token is treated as "not found"
|
// not throw (see #5395), so such a reference token is treated as "not found"
|
||||||
errno = 0; // strtoull() does not reset errno on success
|
errno = 0; // strtoull() does not reset errno on success
|
||||||
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||||
const unsigned long long magnitude = std::strtoull(reference_token.c_str(), &p_end, 10); // NOLINT(runtime/int)
|
const unsigned long long magnitude = std::strtoull(reference_token.data(), &p_end, 10); // NOLINT(runtime/int)
|
||||||
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
||||||
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||||
{
|
{
|
||||||
@@ -32017,7 +32019,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
|
||||||
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
||||||
{
|
{
|
||||||
parser(detail::input_adapter(i)).parse(false, j);
|
// parse into a temporary so that j is left unchanged if parsing fails
|
||||||
|
basic_json result;
|
||||||
|
parser(detail::input_adapter(i)).parse(false, result);
|
||||||
|
j = std::move(result);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|||||||
@@ -352,6 +352,41 @@ TEST_CASE("alternative string type")
|
|||||||
CHECK(j2.flatten().unflatten() == j2);
|
CHECK(j2.flatten().unflatten() == j2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("contains(json_pointer)")
|
||||||
|
{
|
||||||
|
// contains(json_pointer) must compile and work with a string_t that has
|
||||||
|
// no c_str() and no comparison with const char* (see #5666)
|
||||||
|
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
||||||
|
|
||||||
|
// present: object key and array indices
|
||||||
|
CHECK(j.contains(alt_json::json_pointer("/foo")));
|
||||||
|
CHECK(j.contains(alt_json::json_pointer("/foo/0")));
|
||||||
|
CHECK(j.contains(alt_json::json_pointer("/foo/1")));
|
||||||
|
|
||||||
|
// missing: absent object key and out-of-range array index
|
||||||
|
CHECK_FALSE(j.contains(alt_json::json_pointer("/bar")));
|
||||||
|
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/2")));
|
||||||
|
|
||||||
|
// "-" always fails the range check
|
||||||
|
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/-")));
|
||||||
|
|
||||||
|
// an array index must not have a leading zero
|
||||||
|
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/01")));
|
||||||
|
|
||||||
|
// a reference token that is not a number
|
||||||
|
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/bar")));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("operator/(std::size_t)")
|
||||||
|
{
|
||||||
|
// json_pointer::operator/=(std::size_t) must compile without string_t
|
||||||
|
// being constructible from std::string (see #5666)
|
||||||
|
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
||||||
|
|
||||||
|
CHECK(j.at(alt_json::json_pointer("/foo") / std::size_t(0)) == j["foo"][0]);
|
||||||
|
CHECK(j.at(alt_json::json_pointer("/foo") / std::size_t(1)) == j["foo"][1]);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("patch")
|
SECTION("patch")
|
||||||
{
|
{
|
||||||
alt_json const patch1 = alt_json::parse(R"([{ "op": "add", "path": "/a/b", "value": [ "foo", "bar" ] }])");
|
alt_json const patch1 = alt_json::parse(R"([{ "op": "add", "path": "/a/b", "value": [ "foo", "bar" ] }])");
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ using nlohmann::json;
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
TEST_CASE("Better diagnostics")
|
TEST_CASE("Better diagnostics")
|
||||||
{
|
{
|
||||||
@@ -492,6 +493,21 @@ TEST_CASE("Regression tests for extended diagnostics")
|
|||||||
CHECK(copy == j);
|
CHECK(copy == j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Regression test for issue #5652 - operator>> leaves a partial value in its target on a parse error")
|
||||||
|
{
|
||||||
|
json j = "old value";
|
||||||
|
std::istringstream is("[1, x");
|
||||||
|
CHECK_THROWS_WITH_AS(is >> j, "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: '1, x'", json::parse_error);
|
||||||
|
|
||||||
|
// j must be left unchanged, as json::parse() guarantees for its result
|
||||||
|
CHECK(j == "old value");
|
||||||
|
|
||||||
|
// copying j must not trigger assert_invariant(): a failed parse must
|
||||||
|
// not leave array/object elements without a parent pointer
|
||||||
|
json const copy = j; // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
|
CHECK(copy == j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Better diagnostics past the descent bound of update() and merge_patch()")
|
TEST_CASE("Better diagnostics past the descent bound of update() and merge_patch()")
|
||||||
|
|||||||
Reference in New Issue
Block a user