mirror of
https://github.com/nlohmann/json.git
synced 2026-10-03 05:00:30 +00:00
* docs: document that a NUL byte in the input is treated as end of input A NUL byte anywhere in the input - trailing, or embedded ahead of more otherwise well-formed JSON - is currently treated the same as genuine end of input, so parsing silently stops there instead of raising the parse_error.101 any other unexpected byte triggers. This mirrors the NUL-terminated-C-string convention already used when no explicit input length is given (json::parse(const char*) already stops at strlen()), just applied uniformly rather than only when a length is genuinely unavailable. This behavior predates this change and is not being altered here - changing it would be an observable, backwards-incompatible behavior change for any caller that (knowingly or not) depends on it, which is not something to do silently in a patch. Documenting the current, verified behavior as a new FAQ entry instead, so it's an intentional and discoverable part of the contract rather than a surprise. Fixes #5530. Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com> Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4RQ1Ahan5YAGbnAQGjZTY * Add JSON_STRICT_NUL_HANDLING opt-in macro for issue #5530 A NUL byte anywhere in the input is currently treated the same as real end of input, rather than raising parse_error.101 like any other unexpected byte (documented in the previous commit's FAQ entry). A full unconditional fix was tried in PR #5532 but rejected as too risky to ship by default: any caller could depend on the current behavior, even unknowingly (e.g. a zero-padded buffer). On PR #5534, gregmarr proposed a compile-time opt-in flag instead, and the maintainer agreed, wanting it available now and defaulting to the corrected behavior in 4.0.0. This mirrors the existing JSON_BRACE_INIT_COPY_SEMANTICS precedent as closely as sensible: - JSON_STRICT_NUL_HANDLING defaults to 0 (off); the three lexer sites that treat '\0' as EOF/comment-terminator are gated with `#if !JSON_STRICT_NUL_HANDLING` so the default-off behavior is byte-for-byte identical to today's. - input_adapters.hpp's `T (&array)[N]` overload additionally trims a single trailing '\0' from a `char` array (e.g. a string literal like `json::parse("123")`) when the macro is on, so that case keeps working; every other element type (unsigned char, std::uint8_t, ...) always keeps its full extent. This intentionally does *not* reuse the existing strlen()-based pointer overload via SFINAE-excluding `char` from the array overload, as originally sketched for this change: that approach is ambiguous against the newer generic container overload added since PR #5532, and even where it compiles, strlen()-scanning a `char` array that is not NUL-terminated within its bounds reads past the end of the array (confirmed with AddressSanitizer). Trimming only a single trailing byte, without scanning, avoids both problems. - Documented via docs/mkdocs/docs/api/macros/json_strict_nul_handling.md, linked from the macros index/nav/features page, the FAQ entry, and the parse/accept/operator>> reference pages. - Tested in unit-class_parser.cpp and unit-deserialization.cpp, default state unguarded and opt-in state guarded. Since the library itself #undefs the macro at the end of json.hpp (as JSON_BRACE_INIT_COPY_SEMANTICS already does), a plain `#if defined(JSON_STRICT_NUL_HANDLING)` guard after the include never actually triggers; the tests instead capture the command-line value into a test-local macro before including the header. A few pre-existing fixtures elsewhere (std::array<uint8_t, N> sized one larger than their literal, relying on value-initialization to silently add a trailing zero byte) needed the same one-byte adjustment to keep passing under the opt-in behavior. Unlike the precedent, this adds a proper `JSON_StrictNulHandling` CMake option (rather than a raw -DCMAKE_CXX_FLAGS injection) and wires its ci_test_strict_nul_handling target into the ci_cmake_options job matrix in .github/workflows/ubuntu.yml, so the opt-in build is actually exercised in CI -- closing the one gap in the precedent's own CI setup (ci_test_brace_init_copy_semantics is defined but never referenced by any workflow, so it has never actually run). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Clarify where JSON_STRICT_NUL_HANDLING does not reject NUL bytes Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com> Signed-off-by: Niels Lohmann <mail@nlohmann.me> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
226 lines
8.9 KiB
Markdown
226 lines
8.9 KiB
Markdown
# CMake
|
|
|
|
## Integration
|
|
|
|
You can use the `nlohmann_json::nlohmann_json` interface target in CMake. This target populates the appropriate usage
|
|
requirements for [`INTERFACE_INCLUDE_DIRECTORIES`](https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES.html)
|
|
to point to the appropriate include directories and [`INTERFACE_COMPILE_FEATURES`](https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_COMPILE_FEATURES.html)
|
|
for the necessary C++11 flags.
|
|
|
|
### External
|
|
|
|
To use this library from a CMake project, you can locate it directly with [`find_package()`](https://cmake.org/cmake/help/latest/command/find_package.html)
|
|
and use the namespaced imported target from the generated package configuration:
|
|
|
|
!!! example
|
|
|
|
```cmake title="CMakeLists.txt"
|
|
cmake_minimum_required(VERSION 3.5)
|
|
project(ExampleProject LANGUAGES CXX)
|
|
|
|
find_package(nlohmann_json 3.12.0 REQUIRED)
|
|
|
|
add_executable(example example.cpp)
|
|
target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json)
|
|
```
|
|
|
|
The package configuration file, `nlohmann_jsonConfig.cmake`, can be used either from an install tree or directly out of
|
|
the build tree.
|
|
|
|
### Embedded
|
|
|
|
To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call
|
|
`add_subdirectory()` in your `CMakeLists.txt` file.
|
|
|
|
!!! example
|
|
|
|
```cmake title="CMakeLists.txt"
|
|
cmake_minimum_required(VERSION 3.5)
|
|
project(ExampleProject LANGUAGES CXX)
|
|
|
|
# If you only include this third party in PRIVATE source files, you do not need to install it
|
|
# when your main project gets installed.
|
|
set(JSON_Install OFF CACHE INTERNAL "")
|
|
|
|
add_subdirectory(nlohmann_json)
|
|
|
|
add_executable(example example.cpp)
|
|
target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json)
|
|
```
|
|
|
|
!!! note
|
|
|
|
Do not use `#!cmake include(nlohmann_json/CMakeLists.txt)`, since that carries with it unintended consequences that
|
|
will break the build. It is generally discouraged (although not necessarily well documented as such) to use
|
|
`#!cmake include(...)` for pulling in other CMake projects anyways.
|
|
|
|
|
|
### Supporting Both
|
|
|
|
To allow your project to support either an externally supplied or an embedded JSON library, you can use a pattern akin
|
|
to the following.
|
|
|
|
!!! example
|
|
|
|
```cmake title="CMakeLists.txt"
|
|
project(ExampleProject LANGUAGES CXX)
|
|
|
|
option(EXAMPLE_USE_EXTERNAL_JSON "Use an external JSON library" OFF)
|
|
|
|
add_subdirectory(thirdparty)
|
|
|
|
add_executable(example example.cpp)
|
|
|
|
# Note that the namespaced target will always be available regardless of the import method
|
|
target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json)
|
|
```
|
|
|
|
```cmake title="thirdparty/CMakeLists.txt"
|
|
if(EXAMPLE_USE_EXTERNAL_JSON)
|
|
find_package(nlohmann_json 3.12.0 REQUIRED)
|
|
else()
|
|
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
|
add_subdirectory(nlohmann_json)
|
|
endif()
|
|
```
|
|
|
|
`thirdparty/nlohmann_json` is then a complete copy of this source tree.
|
|
|
|
|
|
### FetchContent
|
|
|
|
Since CMake v3.11, [FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can be used to
|
|
automatically download a release as a dependency at configure time.
|
|
|
|
!!! example
|
|
|
|
```cmake title="CMakeLists.txt"
|
|
cmake_minimum_required(VERSION 3.11)
|
|
project(ExampleProject LANGUAGES CXX)
|
|
|
|
include(FetchContent)
|
|
|
|
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz)
|
|
FetchContent_MakeAvailable(json)
|
|
|
|
add_executable(example example.cpp)
|
|
target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json)
|
|
```
|
|
|
|
!!! Note
|
|
|
|
It is recommended to use the URL approach described above which is supported as of version 3.10.0. It is also
|
|
possible to pass the Git repository like
|
|
|
|
```cmake
|
|
FetchContent_Declare(json
|
|
GIT_REPOSITORY https://github.com/nlohmann/json
|
|
GIT_TAG v3.12.0
|
|
)
|
|
```
|
|
|
|
However, the repository <https://github.com/nlohmann/json> download size is quite large.
|
|
|
|
## CMake Options
|
|
|
|
### `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. That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option.
|
|
|
|
### `JSON_CI`
|
|
|
|
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_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.
|
|
|
|
!!! warning "Does not apply to a pre-installed package"
|
|
|
|
This option only takes effect when building nlohmann/json from source as part of your own
|
|
CMake project (e.g. via [`FetchContent`](#fetchcontent) or [`add_subdirectory`](#external)).
|
|
It has **no effect** on a package that was already built and installed elsewhere (Homebrew,
|
|
vcpkg, a system package, etc.) — the resulting compile definition is baked into the exported
|
|
`nlohmann_jsonTargets.cmake` at install time, and `set(JSON_Diagnostics ON)` before
|
|
`find_package()` does not change it (verified against the Homebrew-installed package: the
|
|
exported target still carries a fixed `$<$<BOOL:OFF>:JSON_DIAGNOSTICS=1>`, regardless of any
|
|
variable set in the consuming project).
|
|
|
|
To enable extended diagnostics for a pre-installed package, override the imported target's
|
|
property directly after `find_package()`:
|
|
|
|
```cmake
|
|
find_package(nlohmann_json REQUIRED)
|
|
set_target_properties(nlohmann_json::nlohmann_json PROPERTIES
|
|
INTERFACE_COMPILE_DEFINITIONS "JSON_DIAGNOSTICS=1")
|
|
```
|
|
|
|
This only works cleanly when your project is the sole consumer of that imported target. If
|
|
nlohmann_json is pulled in from more than one place in your dependency graph with different
|
|
`JSON_DIAGNOSTICS` values, you may see a `"JSON_DIAGNOSTICS" redefined` compiler error, since
|
|
conflicting `-D` flags can end up on the same compile command line.
|
|
|
|
### `JSON_Diagnostic_Positions`
|
|
|
|
Enable position diagnostics by defining macro [`JSON_DIAGNOSTIC_POSITIONS`](../api/macros/json_diagnostic_positions.md). This option is `OFF` by default.
|
|
|
|
### `JSON_DisableEnumSerialization`
|
|
|
|
Disable default `enum` serialization by defining the macro
|
|
[`JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). This option is `OFF` by default.
|
|
|
|
### `JSON_FastTests`
|
|
|
|
Skip expensive/slow test suites. This option is `OFF` by default. Depends on `JSON_BuildTests`.
|
|
|
|
### `JSON_GlobalUDLs`
|
|
|
|
Place user-defined string literals in the global namespace by defining the macro
|
|
[`JSON_USE_GLOBAL_UDLS`](../api/macros/json_use_global_udls.md). This option is `OFF` by default.
|
|
|
|
### `JSON_ImplicitConversions`
|
|
|
|
Enable implicit conversions by defining macro [`JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md). This option is `ON` by default.
|
|
|
|
### `JSON_Install`
|
|
|
|
Install CMake targets during install step. This option is `ON` by default if the library's CMake project is the top project.
|
|
|
|
### `JSON_LegacyDiscardedValueComparison`
|
|
|
|
Enable the (incorrect) legacy comparison behavior of discarded JSON values by defining macro [`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](../api/macros/json_use_legacy_discarded_value_comparison.md). This option is `OFF` by default.
|
|
|
|
### `JSON_MultipleHeaders`
|
|
|
|
Use the non-amalgamated version of the library. This option is `ON` by default.
|
|
|
|
### `JSON_SystemInclude`
|
|
|
|
Treat the library headers like system headers (i.e., adding `SYSTEM` to the [`target_include_directories`](https://cmake.org/cmake/help/latest/command/target_include_directories.html) call) to check for this library by tools like Clang-Tidy. This option is `OFF` by default.
|
|
|
|
### `JSON_StrictNulHandling`
|
|
|
|
Reject a `'\0'` (NUL) byte in the input instead of treating it as end of input, by defining the macro
|
|
[`JSON_STRICT_NUL_HANDLING`](../api/macros/json_strict_nul_handling.md). This option is `OFF` by default.
|
|
|
|
### `JSON_Valgrind`
|
|
|
|
Execute the test suite with [Valgrind](https://valgrind.org). This option is `OFF` by default. Depends on `JSON_BuildTests`.
|
|
|
|
### `NLOHMANN_JSON_BUILD_MODULES`
|
|
|
|
Build the experimental [C++ module](../features/modules.md) `nlohmann.json` (requires CMake 3.28 or later and C++20).
|
|
This option is `OFF` by default.
|
|
|
|
A consuming project must link the dedicated `nlohmann_json_modules` CMake target (not just
|
|
`nlohmann_json::nlohmann_json`) for `import nlohmann.json;` to resolve:
|
|
|
|
```cmake
|
|
set(NLOHMANN_JSON_BUILD_MODULES ON)
|
|
add_subdirectory(path/to/json)
|
|
|
|
add_executable(myproject main.cpp)
|
|
target_link_libraries(myproject PRIVATE nlohmann_json_modules)
|
|
target_compile_definitions(myproject PRIVATE NLOHMANN_JSON_BUILD_MODULES)
|
|
```
|