Files
json/docs/mkdocs/docs/integration/cmake.md
Niels Lohmann 3b6ae43c53 Add JSON_DISABLE_TUPLE_REFERENCE_CONVERSION to fix std::tuple conversions (#5598)
* Add JSON_DISABLE_TUPLE_REFERENCE_CONVERSION to fix std::tuple conversions

basic_json can be constructed from std::tuple<json&>, which it turns into
a one-element array. Because of this, std::tuple picks its converting
constructor that converts the whole source tuple instead of the
element-wise one. As a result, std::tuple<const json&> built from
std::forward_as_tuple(j) binds to a temporary (a compile error with libc++,
a dangling reference with other standard libraries), and std::tuple<json>
built the same way holds [j] instead of a copy of j.

The new opt-in macro JSON_DISABLE_TUPLE_REFERENCE_CONVERSION (CMake option
JSON_DisableTupleReferenceConversion) removes the conversion from a
one-element tuple holding a reference to the same basic_json type, so
std::tuple converts element-wise. It is off by default, so existing
behavior is unchanged. It does not change any function body and therefore
is not part of the ABI tag.

Fixes #2226

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* Convert one-element tuples to arrays on every compiler

to_json for std::tuple assigns a braced list, j = { std::get<Idx>(t)... }.
With a single element that is itself a basic_json, Apple clang 15 and 16
treat j = {x} as a copy of x, so std::tuple<json>{true} became true
instead of [true]. The macOS jobs (Xcode 15.1, 16.1) failed the new
checks in unit-disable-tuple-reference-conversion and unit-regression2.

The one-element overload that already handles
JSON_BRACE_INIT_COPY_SEMANTICS builds the array (or object, for a
[string, value] element) explicitly, the same way the initializer-list
constructor does. Use it unconditionally. The output is unchanged on
compilers that already wrapped the element.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* Skip json reference tuple tests on clang < 4 and GCC < 5

ci_test_compilers_gcc_old (4.8) and ci_test_compilers_clang (3.4) could
not compile the new tuple tests. Creating a std::tuple of basic_json
references, e.g. std::forward_as_tuple(j), makes these compilers
instantiate basic_json's conversion operator for libstdc++'s internal
tuple bases, which fails hard. This happens with and without
JSON_DISABLE_TUPLE_REFERENCE_CONVERSION, so it is a limitation of these
compilers, not of the new option.

Tested with the CI images: clang 3.4 to 3.9 and GCC 4.8 and 4.9 fail,
clang 4, 5, and 6 and GCC 5 and 6 compile all cases. Skip only the
checks that create such tuples; the is_constructible checks still run.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 20:53:56 +02:00

9.2 KiB

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 to point to the appropriate include directories and INTERFACE_COMPILE_FEATURES for the necessary C++11 flags.

External

To use this library from a CMake project, you can locate it directly with find_package() 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 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 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 by defining macro JSON_DIAGNOSTICS. 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. This option is OFF by default.

JSON_DisableEnumSerialization

Disable default enum serialization by defining the macro JSON_DISABLE_ENUM_SERIALIZATION. This option is OFF by default.

JSON_DisableTupleReferenceConversion

Disable the conversion from a one-element std::tuple holding a reference to a JSON value by defining the macro JSON_DISABLE_TUPLE_REFERENCE_CONVERSION. 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. This option is OFF by default.

JSON_ImplicitConversions

Enable implicit conversions by defining macro JSON_USE_IMPLICIT_CONVERSIONS. 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. 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 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. This option is OFF by default.

JSON_Valgrind

Execute the test suite with Valgrind. This option is OFF by default. Depends on JSON_BuildTests.

NLOHMANN_JSON_BUILD_MODULES

Build the experimental C++ module 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:

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)