mirror of
https://github.com/nlohmann/json.git
synced 2026-09-30 11:40:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c194c7703d | ||
|
|
71f3554243 |
+1
-1
@@ -10,5 +10,5 @@ title: "JSON for Modern C++"
|
||||
version: 3.12.0
|
||||
date-released: 2025-04-07
|
||||
license: MIT
|
||||
repository-code: "https://github.com/nlohmann/json"
|
||||
repository-code: "https://github.com/nlohmann"
|
||||
url: https://json.nlohmann.me
|
||||
|
||||
+1
-4
@@ -42,11 +42,8 @@ endif()
|
||||
## OPTIONS
|
||||
##
|
||||
|
||||
# Build the tests by default only for the main project and only if the tests
|
||||
# directory exists (the release archive json.tar.xz does not contain it).
|
||||
# VERSION_GREATER_EQUAL is not available in older CMake (< 3.7)
|
||||
if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)
|
||||
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
|
||||
if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13))
|
||||
set(JSON_BuildTests_INIT ON)
|
||||
else()
|
||||
set(JSON_BuildTests_INIT OFF)
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
# find GNU sed to use `-i` parameter
|
||||
SED:=$(shell command -v gsed || which sed)
|
||||
|
||||
# find GNU tar to use `--sort` and `--pax-option` parameters
|
||||
TAR:=$(shell command -v gtar || which tar)
|
||||
|
||||
|
||||
##########################################################################
|
||||
# source files
|
||||
@@ -218,8 +215,8 @@ ChangeLog.md:
|
||||
# archive is created according to the advices of <https://reproducible-builds.org/docs/archives/>.
|
||||
json.tar.xz:
|
||||
mkdir json
|
||||
rsync -R $(shell find LICENSE.MIT nlohmann_json.natvis CMakeLists.txt cmake/*.in include single_include src/modules -type f) json
|
||||
$(TAR) --sort=name --mtime="@$(shell git log -1 --pretty=%ct)" --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime --create --file - json | xz --compress -9e --threads=2 - > json.tar.xz
|
||||
rsync -R $(shell find LICENSE.MIT nlohmann_json.natvis CMakeLists.txt cmake/*.in include single_include -type f) json
|
||||
gtar --sort=name --mtime="@$(shell git log -1 --pretty=%ct)" --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime --create --file - json | xz --compress -9e --threads=2 - > json.tar.xz
|
||||
rm -fr json
|
||||
|
||||
# We use `-X` to make the resulting ZIP file reproducible, see
|
||||
|
||||
@@ -1204,18 +1204,15 @@ language bindings, format converters, and the like. See the curated [Ecosystem](
|
||||
|
||||
Though it's 2026 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
|
||||
|
||||
- GCC 4.8 - 16.2 (and possibly later)
|
||||
- Clang 3.4 - 22.1 (and possibly later)
|
||||
- Apple Clang 15.0 - 21.0 (and possibly later)
|
||||
- Intel C++ Compiler Classic (icpc) 2021.10
|
||||
- Intel oneAPI DPC++/C++ Compiler (icpx) 2025.3 (and possibly later)
|
||||
- NVIDIA CUDA Compiler (nvcc) 11.8 - 12.6 (and possibly later)
|
||||
- NVIDIA HPC SDK C++ Compiler (nvc++) 25.5 (and possibly later)
|
||||
- Microsoft Visual C++ 2015 / MSVC 19.0 (and possibly later)
|
||||
- Microsoft Visual C++ 2017 / MSVC 19.16 (and possibly later)
|
||||
- Microsoft Visual C++ 2019 / MSVC 19.29 (and possibly later)
|
||||
- Microsoft Visual C++ 2022 / MSVC 19.44 (and possibly later)
|
||||
- Microsoft Visual C++ 2026 / MSVC 19.51 (and possibly later)
|
||||
- GCC 4.8 - 14.2 (and possibly later)
|
||||
- Clang 3.4 - 21.0 (and possibly later)
|
||||
- Apple Clang 9.1 - 16.0 (and possibly later)
|
||||
- Intel C++ Compiler 17.0.2 (and possibly later)
|
||||
- Nvidia CUDA Compiler 11.0.221 (and possibly later)
|
||||
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
|
||||
- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
|
||||
- Microsoft Visual C++ 2019 / Build Tools 16.3.1+1def00d3d (and possibly later)
|
||||
- Microsoft Visual C++ 2022 / Build Tools 19.30.30709.0 (and possibly later)
|
||||
|
||||
I would be happy to learn about other compilers/versions.
|
||||
|
||||
|
||||
@@ -37,6 +37,25 @@ Thereby, `Target` is the current object; that is, the patch is applied to the cu
|
||||
|
||||
Linear in the lengths of `apply_patch`.
|
||||
|
||||
## Notes
|
||||
|
||||
!!! danger "Undefined behavior and runtime assertions"
|
||||
|
||||
`merge_patch()` reads `apply_patch` while it modifies `#!cpp *this`. `apply_patch` must not be `#!cpp *this`
|
||||
itself and must not refer to a value contained in `#!cpp *this` (for example, a subobject returned by
|
||||
`#!cpp (*this)[key]`). Calling `merge_patch()` with such an argument reads the argument after it has been
|
||||
invalidated by the modification, which is undefined behavior. If the patch may alias `#!cpp *this`, pass a copy
|
||||
instead:
|
||||
|
||||
```cpp
|
||||
j.merge_patch(json(j)); // instead of j.merge_patch(j)
|
||||
```
|
||||
|
||||
Passing `#!cpp *this` itself is **guarded by a [runtime assertion](../../features/assertions.md)**; a value
|
||||
contained in `#!cpp *this` is not detected.
|
||||
|
||||
See [GitHub issue #5641](https://github.com/nlohmann/json/issues/5641) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -61,3 +80,5 @@ Linear in the lengths of `apply_patch`.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.0.0.
|
||||
- Documented that `apply_patch` must not be `#!cpp *this` or refer to a value contained in `#!cpp *this`, in version
|
||||
3.13.0.
|
||||
|
||||
@@ -59,6 +59,25 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
||||
1. O(N*log(size() + N)), where N is the number of elements to insert.
|
||||
2. O(N*log(size() + N)), where N is the number of elements to insert.
|
||||
|
||||
## Notes
|
||||
|
||||
!!! danger "Undefined behavior and runtime assertions"
|
||||
|
||||
Both overloads read the argument while they modify `#!cpp *this`. The argument `j` (or, for overload (2), the
|
||||
range `[first, last)`) must not be `#!cpp *this` itself and must not refer to a value contained in
|
||||
`#!cpp *this` (for example, a subobject returned by `#!cpp (*this)[key]`). Calling `update()` with such an
|
||||
argument reads the argument after it has been invalidated by the modification, which is undefined behavior. If
|
||||
the argument may alias `#!cpp *this`, pass a copy instead:
|
||||
|
||||
```cpp
|
||||
j.update(json(j["defaults"])); // instead of j.update(j["defaults"])
|
||||
```
|
||||
|
||||
Passing `#!cpp *this` itself is **guarded by a [runtime assertion](../../features/assertions.md)**; a value
|
||||
contained in `#!cpp *this` is not detected.
|
||||
|
||||
See [GitHub issue #5641](https://github.com/nlohmann/json/issues/5641) for more information.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -155,3 +174,5 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
||||
|
||||
- Added in version 3.0.0.
|
||||
- Added `merge_objects` parameter in 3.10.5.
|
||||
- Documented that the argument must not be `#!cpp *this` or refer to a value contained in `#!cpp *this`, in version
|
||||
3.13.0.
|
||||
|
||||
@@ -103,6 +103,36 @@ behavior and yields a runtime assertion.
|
||||
Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368.
|
||||
```
|
||||
|
||||
### Updating or merge-patching a value with itself
|
||||
|
||||
Functions [`update`](../api/basic_json/update.md) and [`merge_patch`](../api/basic_json/merge_patch.md) read their
|
||||
argument while they modify the value they are called on. Passing that value itself as the argument is undefined
|
||||
behavior and yields a runtime assertion. Pass a copy instead, for example `#!cpp j.merge_patch(json(j))`. An argument
|
||||
that refers to a value contained in the value (e.g., `#!cpp j.update(j["defaults"])`) is undefined behavior as well, but
|
||||
is not detected.
|
||||
|
||||
??? example "Example 4: Merge-patching a value with itself"
|
||||
|
||||
The following code will trigger an assertion at runtime:
|
||||
|
||||
```cpp
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
json j = {{"key", "value"}};
|
||||
j.merge_patch(j);
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Assertion failed: (&apply_patch != this), function merge_patch, file json.hpp, line 6310.
|
||||
```
|
||||
|
||||
## Changes
|
||||
|
||||
### Reading from a null `FILE` or `char` pointer
|
||||
|
||||
@@ -125,7 +125,7 @@ automatically download a release as a dependency at configure time.
|
||||
|
||||
### `JSON_BuildTests`
|
||||
|
||||
Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project and the `tests` directory exists (the release archive `json.tar.xz` does not contain it). That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option.
|
||||
Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project. That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option.
|
||||
|
||||
### `JSON_CI`
|
||||
|
||||
|
||||
@@ -4218,6 +4218,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
|
||||
}
|
||||
|
||||
// the range must not be *this; a range inside *this is not detected
|
||||
JSON_ASSERT(first.m_object != this);
|
||||
|
||||
update_members(first, last, merge_objects, 0);
|
||||
}
|
||||
|
||||
@@ -6303,6 +6306,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
|
||||
void merge_patch(const basic_json& apply_patch)
|
||||
{
|
||||
// the patch must not be *this; a patch inside *this is not detected
|
||||
JSON_ASSERT(&apply_patch != this);
|
||||
|
||||
apply_merge_patch(apply_patch, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -30299,6 +30299,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
|
||||
}
|
||||
|
||||
// the range must not be *this; a range inside *this is not detected
|
||||
JSON_ASSERT(first.m_object != this);
|
||||
|
||||
update_members(first, last, merge_objects, 0);
|
||||
}
|
||||
|
||||
@@ -32384,6 +32387,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
|
||||
void merge_patch(const basic_json& apply_patch)
|
||||
{
|
||||
// the patch must not be *this; a patch inside *this is not detected
|
||||
JSON_ASSERT(&apply_patch != this);
|
||||
|
||||
apply_merge_patch(apply_patch, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,33 @@ TEST_CASE("JSON_ASSERT(x)")
|
||||
// check that assertion actually happened
|
||||
CHECK(assert_counter == 1);
|
||||
}
|
||||
|
||||
SECTION("update() and merge_patch() with *this")
|
||||
{
|
||||
// update() and merge_patch() must not be called with *this (#5641);
|
||||
// the values are chosen so the calls still happen to work without
|
||||
// aborting, and only the assertion counter is checked
|
||||
json j = {{"a", 1}};
|
||||
|
||||
assert_counter = 0;
|
||||
j.update(j);
|
||||
CHECK(assert_counter == 1);
|
||||
|
||||
assert_counter = 0;
|
||||
j.update(j.cbegin(), j.cend());
|
||||
CHECK(assert_counter == 1);
|
||||
|
||||
assert_counter = 0;
|
||||
j.merge_patch(j);
|
||||
CHECK(assert_counter == 1);
|
||||
|
||||
// a copy is fine
|
||||
assert_counter = 0;
|
||||
j.update(json(j));
|
||||
j.merge_patch(json(j));
|
||||
CHECK(assert_counter == 0);
|
||||
CHECK(j == json({{"a", 1}}));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user