Merge branch 'develop' of https://github.com/nlohmann/json into update_doctest

This commit is contained in:
Niels Lohmann 2022-03-24 07:55:48 +01:00
commit 78580ca8bd
No known key found for this signature in database
GPG Key ID: 7F3CEA63AE251B69
47 changed files with 1606 additions and 787 deletions

View File

@ -9,6 +9,7 @@ on:
pull_request: pull_request:
schedule: schedule:
- cron: '0 19 * * 1' - cron: '0 19 * * 1'
workflow_dispatch:
jobs: jobs:
CodeQL-Build: CodeQL-Build:

View File

@ -7,6 +7,7 @@ on:
- master - master
- release/* - release/*
pull_request: pull_request:
workflow_dispatch:
jobs: jobs:
xcode: xcode:
@ -37,7 +38,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: cmake - name: cmake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DCMAKE_CXX_STANDARD_REQUIRED=ON run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_TestStandards=${{ matrix.standard }}
- name: build - name: build
run: cmake --build build --parallel 10 run: cmake --build build --parallel 10
- name: test - name: test

View File

@ -7,6 +7,7 @@ on:
- master - master
- release/* - release/*
pull_request: pull_request:
workflow_dispatch:
jobs: jobs:
ci_test_clang: ci_test_clang:

View File

@ -7,6 +7,7 @@ on:
- master - master
- release/* - release/*
pull_request: pull_request:
workflow_dispatch:
jobs: jobs:
mingw: mingw:
@ -64,7 +65,7 @@ jobs:
run: cd build ; ctest -j 10 -C Release --output-on-failure run: cd build ; ctest -j 10 -C Release --output-on-failure
msvc2019: msvc2019:
runs-on: windows-latest runs-on: windows-2019
strategy: strategy:
matrix: matrix:
build_type: [Debug, Release] build_type: [Debug, Release]
@ -84,7 +85,7 @@ jobs:
run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure
msvc2019_latest: msvc2019_latest:
runs-on: windows-latest runs-on: windows-2019
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -95,8 +96,40 @@ jobs:
- name: test - name: test
run: cd build ; ctest -j 10 -C Release --output-on-failure run: cd build ; ctest -j 10 -C Release --output-on-failure
msvc2022:
runs-on: windows-2022
strategy:
matrix:
build_type: [Debug, Release]
architecture: [Win32, x64]
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
if: matrix.build_type == 'Release'
- name: cmake
run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_FLAGS="/W4 /WX"
if: matrix.build_type == 'Debug'
- name: build
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
- name: test
run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure
msvc2022_latest:
runs-on: windows-2022
steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX"
- name: build
run: cmake --build build --config Release --parallel 10
- name: test
run: cd build ; ctest -j 10 -C Release --output-on-failure
clang: clang:
runs-on: windows-latest runs-on: windows-2019
strategy: strategy:
matrix: matrix:
version: [11, 12] version: [11, 12]
@ -113,7 +146,7 @@ jobs:
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure
clang-cl-11: clang-cl-11:
runs-on: windows-latest runs-on: windows-2019
strategy: strategy:
matrix: matrix:
architecture: [Win32, x64] architecture: [Win32, x64]

View File

@ -1,6 +1,6 @@
cff-version: 1.1.0 cff-version: 1.2.0
message: "If you use this software, please cite it as below." message: "If you use this software, please cite it as below."
authors: authors:
- family-names: Lohmann - family-names: Lohmann
given-names: Niels given-names: Niels
orcid: https://orcid.org/0000-0001-9037-795X orcid: https://orcid.org/0000-0001-9037-795X
@ -8,7 +8,7 @@ authors:
website: https://nlohmann.me website: https://nlohmann.me
title: "JSON for Modern C++" title: "JSON for Modern C++"
version: 3.10.5 version: 3.10.5
date-released: 2022 date-released: 2022-01-03
license: MIT license: MIT
repository-code: "https://github.com/nlohmann" repository-code: "https://github.com/nlohmann"
url: https://json.nlohmann.me url: https://json.nlohmann.me

View File

@ -19,6 +19,7 @@ endif()
## INCLUDE ## INCLUDE
## ##
## ##
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
include(ExternalProject) include(ExternalProject)
## ##
@ -30,7 +31,13 @@ if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW) cmake_policy(SET CMP0077 NEW)
endif () endif ()
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${MAIN_PROJECT}) # VERSION_GREATER_EQUAL is not available in CMake 3.1
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)
endif()
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${JSON_BuildTests_INIT})
option(JSON_CI "Enable CI build targets." OFF) option(JSON_CI "Enable CI build targets." OFF)
option(JSON_Diagnostics "Use extended diagnostic messages." OFF) option(JSON_Diagnostics "Use extended diagnostic messages." OFF)
option(JSON_ImplicitConversions "Enable implicit conversions." ON) option(JSON_ImplicitConversions "Enable implicit conversions." ON)
@ -39,7 +46,7 @@ option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OF
option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF)
if (JSON_CI) if (JSON_CI)
include(cmake/ci.cmake) include(ci)
endif () endif ()
## ##

View File

@ -4,9 +4,6 @@
# configuration # configuration
########################################################################## ##########################################################################
# directory to recent compiler binaries
COMPILER_DIR=/usr/local/opt/llvm/bin
# find GNU sed to use `-i` parameter # find GNU sed to use `-i` parameter
SED:=$(shell command -v gsed || which sed) SED:=$(shell command -v gsed || which sed)
@ -62,6 +59,7 @@ run_benchmarks:
cd cmake-build-benchmarks ; ninja cd cmake-build-benchmarks ; ninja
cd cmake-build-benchmarks ; ./json_benchmarks cd cmake-build-benchmarks ; ./json_benchmarks
########################################################################## ##########################################################################
# fuzzing # fuzzing
########################################################################## ##########################################################################
@ -135,6 +133,7 @@ pvs_studio:
cd cmake-build-pvs-studio ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs cd cmake-build-pvs-studio ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
open cmake-build-pvs-studio/pvs/index.html open cmake-build-pvs-studio/pvs/index.html
########################################################################## ##########################################################################
# Code format and source amalgamation # Code format and source amalgamation
########################################################################## ##########################################################################
@ -203,20 +202,29 @@ ChangeLog.md:
# Release files # Release files
########################################################################## ##########################################################################
# Create the files for a release and add signatures and hashes. We use `-X` to make the resulting ZIP file # Create a tar.gz archive that contains sufficient files to be used as CMake project (e.g., using FetchContent). The
# reproducible, see <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>. # 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 -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
release: # We use `-X` to make the resulting ZIP file reproducible, see
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
include.zip:
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) meson.build LICENSE.MIT
# Create the files for a release and add signatures and hashes.
release: include.zip json.tar.xz
rm -fr release_files rm -fr release_files
mkdir release_files mkdir release_files
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) meson.build LICENSE.MIT
gpg --armor --detach-sig include.zip gpg --armor --detach-sig include.zip
mv include.zip include.zip.asc release_files
gpg --armor --detach-sig $(AMALGAMATED_FILE) gpg --armor --detach-sig $(AMALGAMATED_FILE)
gpg --armor --detach-sig json.tar.xz
cp $(AMALGAMATED_FILE) release_files cp $(AMALGAMATED_FILE) release_files
mv $(AMALGAMATED_FILE).asc release_files mv $(AMALGAMATED_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
cd release_files ; shasum -a 256 json.hpp > hashes.txt cd release_files ; shasum -a 256 json.hpp include.zip json.tar.xz > hashes.txt
cd release_files ; shasum -a 256 include.zip >> hashes.txt
########################################################################## ##########################################################################
@ -225,12 +233,12 @@ release:
# clean up # clean up
clean: clean:
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM oclint_report.html rm -fr fuzz fuzz-testing *.dSYM test/*.dSYM
rm -fr benchmarks/files/numbers/*.json rm -fr benchmarks/files/numbers/*.json
rm -fr cmake-3.1.0-Darwin64.tar.gz cmake-3.1.0-Darwin64 rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files
rm -fr cmake-build-benchmarks cmake-build-pedantic fuzz-testing cmake-build-clang-analyze cmake-build-pvs-studio cmake-build-infer cmake_build
$(MAKE) clean -Cdoc $(MAKE) clean -Cdoc
########################################################################## ##########################################################################
# Thirdparty code # Thirdparty code
########################################################################## ##########################################################################

View File

@ -10,7 +10,7 @@
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/nlohmann/json.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nlohmann/json/context:cpp) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/nlohmann/json.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nlohmann/json/context:cpp)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/json.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/json.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/1mp10JbaANo6FUc7) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](https://nlohmann.github.io/json/doxygen/index.html) [![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://json.nlohmann.me)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
[![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) [![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
[![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases) [![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases)
@ -85,7 +85,7 @@ Thanks everyone!
:books: If you want to **learn more** about how to use the library, check out the rest of the [**README**](#examples), have a look at [**code examples**](https://github.com/nlohmann/json/tree/develop/doc/examples), or browse through the [**help pages**](https://json.nlohmann.me). :books: If you want to **learn more** about how to use the library, check out the rest of the [**README**](#examples), have a look at [**code examples**](https://github.com/nlohmann/json/tree/develop/doc/examples), or browse through the [**help pages**](https://json.nlohmann.me).
:construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/) or the [**Doxygen documentation**](https://json.nlohmann.me/doxygen/index.html). :construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/).
:bug: If you found a **bug**, please check the [**FAQ**](https://json.nlohmann.me/home/faq/) if it is a known issue or the result of a design decision. Please also have a look at the [**issue list**](https://github.com/nlohmann/json/issues) before you [**create a new issue**](https://github.com/nlohmann/json/issues/new/choose). Please provide as much information as possible to help us understand and reproduce your issue. :bug: If you found a **bug**, please check the [**FAQ**](https://json.nlohmann.me/home/faq/) if it is a known issue or the result of a design decision. Please also have a look at the [**issue list**](https://github.com/nlohmann/json/issues) before you [**create a new issue**](https://github.com/nlohmann/json/issues/new/choose). Please provide as much information as possible to help us understand and reproduce your issue.
@ -1045,6 +1045,7 @@ Though it's 2022 already, the support for C++11 is still a bit sparse. Currently
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (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++ 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++ 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. I would be happy to learn about other compilers/versions.
@ -1119,6 +1120,7 @@ The following compilers are currently used in continuous integration at [AppVeyo
| Visual Studio 15 2017 MSVC 19.16.27045.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | GitHub Actions | | Visual Studio 15 2017 MSVC 19.16.27045.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | GitHub Actions |
| Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | GitHub Actions | | Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | GitHub Actions |
| Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | AppVeyor | | Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | AppVeyor |
| Visual Studio 17 2022 MSVC 19.30.30709.0 (Build Engine version 17.0.31804.368 for .NET Framework) | Windows-10.0.20348 | GitHub Actions |
## Integration ## Integration
@ -1183,29 +1185,20 @@ target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
Since CMake v3.11, Since CMake v3.11,
[FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can [FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can
be used to automatically download the repository as a dependency at configure time. be used to automatically download a release as a dependency at configure time.
Example: Example:
```cmake ```cmake
include(FetchContent) include(FetchContent)
FetchContent_Declare(json FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.10.5/json.tar.xz)
GIT_REPOSITORY https://github.com/nlohmann/json.git FetchContent_MakeAvailable(json)
GIT_TAG v3.7.3)
FetchContent_GetProperties(json)
if(NOT json_POPULATED)
FetchContent_Populate(json)
add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
``` ```
**Note**: The repository https://github.com/nlohmann/json download size is huge. **Note**: It is recommended to use the URL approach described above which is supported as of version 3.10.0. See
It contains all the dataset used for the benchmarks. You might want to depend on <https://json.nlohmann.me/integration/cmake/#fetchcontent> for more information.
a smaller repository. For instance, you might want to replace the URL above by
https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent
#### Supporting Both #### Supporting Both
@ -1624,13 +1617,14 @@ The library itself consists of a single header file licensed under the MIT licen
- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json) - [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json)
- [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis - [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis
- [**doctest**](https://github.com/onqtam/doctest) for the unit tests - [**doctest**](https://github.com/onqtam/doctest) for the unit tests
- [**Doxygen**](https://www.doxygen.nl/index.html) to generate [documentation](https://nlohmann.github.io/json/doxygen/index.html)
- [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages - [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages
- [**GitHub Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md) - [**GitHub Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md)
- [**Google Benchmark**](https://github.com/google/benchmark) to implement the benchmarks - [**Google Benchmark**](https://github.com/google/benchmark) to implement the benchmarks
- [**Hedley**](https://nemequ.github.io/hedley/) to avoid re-inventing several compiler-agnostic feature macros - [**Hedley**](https://nemequ.github.io/hedley/) to avoid re-inventing several compiler-agnostic feature macros
- [**lcov**](http://ltp.sourceforge.net/coverage/lcov.php) to process coverage information and create an HTML view - [**lcov**](http://ltp.sourceforge.net/coverage/lcov.php) to process coverage information and create an HTML view
- [**libFuzzer**](https://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz - [**libFuzzer**](https://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz
- [**Material for MkDocs**](https://squidfunk.github.io/mkdocs-material/) for the style of the documentation site
- [**MkDocs**](https://www.mkdocs.org) for the documentation site
- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json)) - [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json))
- [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments. - [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments.
- [**Valgrind**](https://valgrind.org) to check for correct memory management - [**Valgrind**](https://valgrind.org) to check for correct memory management

View File

@ -23,7 +23,7 @@ if(NOT benchmark_POPULATED)
endif() endif()
# download test data # download test data
include(${CMAKE_SOURCE_DIR}/../cmake/download_test_data.cmake) include(download_test_data)
# benchmark binary # benchmark binary
add_executable(json_benchmarks src/benchmarks.cpp) add_executable(json_benchmarks src/benchmarks.cpp)

View File

@ -30,7 +30,7 @@ execute_process(COMMAND ${CPPCHECK_TOOL} --version OUTPUT_VARIABLE CPPCHECK_TOOL
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CPPCHECK_TOOL_VERSION "${CPPCHECK_TOOL_VERSION}") string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CPPCHECK_TOOL_VERSION "${CPPCHECK_TOOL_VERSION}")
message(STATUS "🔖 Cppcheck ${CPPCHECK_TOOL_VERSION} (${CPPCHECK_TOOL})") message(STATUS "🔖 Cppcheck ${CPPCHECK_TOOL_VERSION} (${CPPCHECK_TOOL})")
find_program(GCC_TOOL NAMES g++-HEAD g++-11 g++-latest) find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++-11)
execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION) execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}") string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}")
message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})") message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})")
@ -98,19 +98,20 @@ file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp)
# -Wno-weak-vtables The library is header-only. # -Wno-weak-vtables The library is header-only.
# -Wreserved-identifier See https://github.com/onqtam/doctest/issues/536. # -Wreserved-identifier See https://github.com/onqtam/doctest/issues/536.
set(CLANG_CXXFLAGS "-std=c++11 \ set(CLANG_CXXFLAGS
-Werror \ -Werror
-Weverything \ -Weverything
-Wno-c++98-compat \ -Wno-c++98-compat
-Wno-c++98-compat-pedantic \ -Wno-c++98-compat-pedantic
-Wno-deprecated-declarations \ -Wno-deprecated-declarations
-Wno-extra-semi-stmt \ -Wno-extra-semi-stmt
-Wno-padded \ -Wno-padded
-Wno-covered-switch-default \ -Wno-covered-switch-default
-Wno-weak-vtables \ -Wno-weak-vtables
-Wno-reserved-identifier \ -Wno-reserved-identifier
") )
# Warning flags determined for GCC 12.0 (experimental) with https://github.com/nlohmann/gcc_flags:
# Ignored GCC warnings: # Ignored GCC warnings:
# -Wno-abi-tag We do not care about ABI tags. # -Wno-abi-tag We do not care about ABI tags.
# -Wno-aggregate-return The library uses aggregate returns. # -Wno-aggregate-return The library uses aggregate returns.
@ -120,283 +121,295 @@ set(CLANG_CXXFLAGS "-std=c++11 \
# -Wno-system-headers We do not care about warnings in system headers. # -Wno-system-headers We do not care about warnings in system headers.
# -Wno-templates The library uses templates. # -Wno-templates The library uses templates.
set(GCC_CXXFLAGS "-std=c++11 \ set(GCC_CXXFLAGS
-pedantic \ -pedantic
-Werror \ -Werror
--all-warnings \ --all-warnings
--extra-warnings \ --extra-warnings
-W \ -W
-WNSObject-attribute \ -WNSObject-attribute
-Wno-abi-tag \ -Wno-abi-tag
-Waddress \ -Waddress
-Waddress-of-packed-member \ -Waddress-of-packed-member
-Wno-aggregate-return \ -Wno-aggregate-return
-Waggressive-loop-optimizations \ -Waggressive-loop-optimizations
-Waligned-new=all \ -Waligned-new=all
-Wall \ -Wall
-Walloc-zero \ -Walloc-zero
-Walloca \ -Walloca
-Wanalyzer-double-fclose \ -Wanalyzer-double-fclose
-Wanalyzer-double-free \ -Wanalyzer-double-free
-Wanalyzer-exposure-through-output-file \ -Wanalyzer-exposure-through-output-file
-Wanalyzer-file-leak \ -Wanalyzer-file-leak
-Wanalyzer-free-of-non-heap \ -Wanalyzer-free-of-non-heap
-Wanalyzer-malloc-leak \ -Wanalyzer-malloc-leak
-Wanalyzer-mismatching-deallocation \ -Wanalyzer-mismatching-deallocation
-Wanalyzer-null-argument \ -Wanalyzer-null-argument
-Wanalyzer-null-dereference \ -Wanalyzer-null-dereference
-Wanalyzer-possible-null-argument \ -Wanalyzer-possible-null-argument
-Wanalyzer-possible-null-dereference \ -Wanalyzer-possible-null-dereference
-Wanalyzer-shift-count-negative \ -Wanalyzer-shift-count-negative
-Wanalyzer-shift-count-overflow \ -Wanalyzer-shift-count-overflow
-Wanalyzer-stale-setjmp-buffer \ -Wanalyzer-stale-setjmp-buffer
-Wanalyzer-tainted-array-index \ -Wanalyzer-tainted-allocation-size
-Wanalyzer-too-complex \ -Wanalyzer-tainted-array-index
-Wanalyzer-unsafe-call-within-signal-handler \ -Wanalyzer-tainted-divisor
-Wanalyzer-use-after-free \ -Wanalyzer-tainted-offset
-Wanalyzer-use-of-pointer-in-stale-stack-frame \ -Wanalyzer-tainted-size
-Wanalyzer-write-to-const \ -Wanalyzer-too-complex
-Wanalyzer-write-to-string-literal \ -Wanalyzer-unsafe-call-within-signal-handler
-Warith-conversion \ -Wanalyzer-use-after-free
-Warray-bounds \ -Wanalyzer-use-of-pointer-in-stale-stack-frame
-Warray-bounds=2 \ -Wanalyzer-use-of-uninitialized-value
-Warray-parameter=2 \ -Wanalyzer-write-to-const
-Wattribute-alias=2 \ -Wanalyzer-write-to-string-literal
-Wattribute-warning \ -Warith-conversion
-Wattributes \ -Warray-bounds
-Wbool-compare \ -Warray-bounds=2
-Wbool-operation \ -Warray-compare
-Wbuiltin-declaration-mismatch \ -Warray-parameter=2
-Wbuiltin-macro-redefined \ -Wattribute-alias=2
-Wc++0x-compat \ -Wattribute-warning
-Wc++11-compat \ -Wattributes
-Wc++14-compat \ -Wbool-compare
-Wc++17-compat \ -Wbool-operation
-Wc++1z-compat \ -Wbuiltin-declaration-mismatch
-Wc++20-compat \ -Wbuiltin-macro-redefined
-Wc++2a-compat \ -Wc++0x-compat
-Wcannot-profile \ -Wc++11-compat
-Wcast-align \ -Wc++11-extensions
-Wcast-align=strict \ -Wc++14-compat
-Wcast-function-type \ -Wc++14-extensions
-Wcast-qual \ -Wc++17-compat
-Wcatch-value=3 \ -Wc++17-extensions
-Wchar-subscripts \ -Wc++1z-compat
-Wclass-conversion \ -Wc++20-compat
-Wclass-memaccess \ -Wc++20-extensions
-Wclobbered \ -Wc++23-extensions
-Wcomma-subscript \ -Wc++2a-compat
-Wcomment \ -Wcannot-profile
-Wcomments \ -Wcast-align
-Wconditionally-supported \ -Wcast-align=strict
-Wconversion \ -Wcast-function-type
-Wconversion-null \ -Wcast-qual
-Wcoverage-mismatch \ -Wcatch-value=3
-Wcpp \ -Wchar-subscripts
-Wctad-maybe-unsupported \ -Wclass-conversion
-Wctor-dtor-privacy \ -Wclass-memaccess
-Wdangling-else \ -Wclobbered
-Wdate-time \ -Wcomma-subscript
-Wdelete-incomplete \ -Wcomment
-Wdelete-non-virtual-dtor \ -Wcomments
-Wdeprecated \ -Wconditionally-supported
-Wdeprecated-copy \ -Wconversion
-Wdeprecated-copy-dtor \ -Wconversion-null
-Wdeprecated-declarations \ -Wcoverage-invalid-line-number
-Wdeprecated-enum-enum-conversion \ -Wcoverage-mismatch
-Wdeprecated-enum-float-conversion \ -Wcpp
-Wdisabled-optimization \ -Wctad-maybe-unsupported
-Wdiv-by-zero \ -Wctor-dtor-privacy
-Wdouble-promotion \ -Wdangling-else
-Wduplicated-branches \ -Wdate-time
-Wduplicated-cond \ -Wdelete-incomplete
-Weffc++ \ -Wdelete-non-virtual-dtor
-Wempty-body \ -Wdeprecated
-Wendif-labels \ -Wdeprecated-copy
-Wenum-compare \ -Wdeprecated-copy-dtor
-Wenum-conversion \ -Wdeprecated-declarations
-Wexpansion-to-defined \ -Wdeprecated-enum-enum-conversion
-Wextra \ -Wdeprecated-enum-float-conversion
-Wextra-semi \ -Wdisabled-optimization
-Wfloat-conversion \ -Wdiv-by-zero
-Wfloat-equal \ -Wdouble-promotion
-Wformat-contains-nul \ -Wduplicated-branches
-Wformat-diag \ -Wduplicated-cond
-Wformat-extra-args \ -Weffc++
-Wformat-nonliteral \ -Wempty-body
-Wformat-overflow=2 \ -Wendif-labels
-Wformat-security \ -Wenum-compare
-Wformat-signedness \ -Wenum-conversion
-Wformat-truncation=2 \ -Wexceptions
-Wformat-y2k \ -Wexpansion-to-defined
-Wformat-zero-length \ -Wextra
-Wformat=2 \ -Wextra-semi
-Wframe-address \ -Wfloat-conversion
-Wfree-nonheap-object \ -Wfloat-equal
-Whsa \ -Wformat-diag
-Wif-not-aligned \ -Wformat-overflow=2
-Wignored-attributes \ -Wformat-signedness
-Wignored-qualifiers \ -Wformat-truncation=2
-Wimplicit-fallthrough=5 \ -Wformat=2
-Winaccessible-base \ -Wframe-address
-Winherited-variadic-ctor \ -Wfree-nonheap-object
-Winit-list-lifetime \ -Whsa
-Winit-self \ -Wif-not-aligned
-Winline \ -Wignored-attributes
-Wint-in-bool-context \ -Wignored-qualifiers
-Wint-to-pointer-cast \ -Wimplicit-fallthrough=5
-Winvalid-memory-model \ -Winaccessible-base
-Winvalid-offsetof \ -Winfinite-recursion
-Winvalid-pch \ -Winherited-variadic-ctor
-Wliteral-suffix \ -Winit-list-lifetime
-Wlogical-not-parentheses \ -Winit-self
-Wlogical-op \ -Winline
-Wno-long-long \ -Wint-in-bool-context
-Wlto-type-mismatch \ -Wint-to-pointer-cast
-Wmain \ -Winterference-size
-Wmaybe-uninitialized \ -Winvalid-imported-macros
-Wmemset-elt-size \ -Winvalid-memory-model
-Wmemset-transposed-args \ -Winvalid-offsetof
-Wmisleading-indentation \ -Winvalid-pch
-Wmismatched-dealloc \ -Wliteral-suffix
-Wmismatched-new-delete \ -Wlogical-not-parentheses
-Wmismatched-tags \ -Wlogical-op
-Wmissing-attributes \ -Wno-long-long
-Wmissing-braces \ -Wlto-type-mismatch
-Wmissing-declarations \ -Wmain
-Wmissing-field-initializers \ -Wmaybe-uninitialized
-Wmissing-include-dirs \ -Wmemset-elt-size
-Wmissing-profile \ -Wmemset-transposed-args
-Wmultichar \ -Wmisleading-indentation
-Wmultiple-inheritance \ -Wmismatched-dealloc
-Wmultistatement-macros \ -Wmismatched-new-delete
-Wno-namespaces \ -Wmismatched-tags
-Wnarrowing \ -Wmissing-attributes
-Wnoexcept \ -Wmissing-braces
-Wnoexcept-type \ -Wmissing-declarations
-Wnon-template-friend \ -Wmissing-field-initializers
-Wnon-virtual-dtor \ -Wmissing-include-dirs
-Wnonnull \ -Wmissing-profile
-Wnonnull-compare \ -Wmissing-requires
-Wnormalized=nfkc \ -Wmultichar
-Wnull-dereference \ -Wmultiple-inheritance
-Wodr \ -Wmultistatement-macros
-Wold-style-cast \ -Wno-namespaces
-Wopenmp-simd \ -Wnarrowing
-Woverflow \ -Wnoexcept
-Woverlength-strings \ -Wnoexcept-type
-Woverloaded-virtual \ -Wnon-template-friend
-Wpacked \ -Wnon-virtual-dtor
-Wpacked-bitfield-compat \ -Wnonnull
-Wpacked-not-aligned \ -Wnonnull-compare
-Wno-padded \ -Wnormalized=nfkc
-Wparentheses \ -Wnull-dereference
-Wpedantic \ -Wodr
-Wpessimizing-move \ -Wold-style-cast
-Wplacement-new=2 \ -Wopenacc-parallelism
-Wpmf-conversions \ -Wopenmp-simd
-Wpointer-arith \ -Woverflow
-Wpointer-compare \ -Woverlength-strings
-Wpragmas \ -Woverloaded-virtual
-Wprio-ctor-dtor \ -Wpacked
-Wpsabi \ -Wpacked-bitfield-compat
-Wrange-loop-construct \ -Wpacked-not-aligned
-Wredundant-decls \ -Wno-padded
-Wredundant-move \ -Wparentheses
-Wredundant-tags \ -Wpedantic
-Wregister \ -Wpessimizing-move
-Wreorder \ -Wplacement-new=2
-Wrestrict \ -Wpmf-conversions
-Wreturn-local-addr \ -Wpointer-arith
-Wreturn-type \ -Wpointer-compare
-Wscalar-storage-order \ -Wpragmas
-Wsequence-point \ -Wprio-ctor-dtor
-Wshadow=compatible-local \ -Wpsabi
-Wshadow=global \ -Wrange-loop-construct
-Wshadow=local \ -Wredundant-decls
-Wshift-count-negative \ -Wredundant-move
-Wshift-count-overflow \ -Wredundant-tags
-Wshift-negative-value \ -Wregister
-Wshift-overflow=2 \ -Wreorder
-Wsign-compare \ -Wrestrict
-Wsign-conversion \ -Wreturn-local-addr
-Wsign-promo \ -Wreturn-type
-Wsized-deallocation \ -Wscalar-storage-order
-Wsizeof-array-argument \ -Wsequence-point
-Wsizeof-array-div \ -Wshadow=compatible-local
-Wsizeof-pointer-div \ -Wshadow=global
-Wsizeof-pointer-memaccess \ -Wshadow=local
-Wstack-protector \ -Wshift-count-negative
-Wstrict-aliasing \ -Wshift-count-overflow
-Wstrict-aliasing=3 \ -Wshift-negative-value
-Wstrict-null-sentinel \ -Wshift-overflow=2
-Wstrict-overflow \ -Wsign-compare
-Wstrict-overflow=5 \ -Wsign-conversion
-Wstring-compare \ -Wsign-promo
-Wstringop-overflow=4 \ -Wsized-deallocation
-Wstringop-overread \ -Wsizeof-array-argument
-Wstringop-truncation \ -Wsizeof-array-div
-Wsubobject-linkage \ -Wsizeof-pointer-div
-Wsuggest-attribute=cold \ -Wsizeof-pointer-memaccess
-Wsuggest-attribute=const \ -Wstack-protector
-Wsuggest-attribute=format \ -Wstrict-aliasing
-Wsuggest-attribute=malloc \ -Wstrict-aliasing=3
-Wsuggest-attribute=noreturn \ -Wstrict-null-sentinel
-Wsuggest-attribute=pure \ -Wstrict-overflow
-Wsuggest-final-methods \ -Wstrict-overflow=5
-Wsuggest-final-types \ -Wstring-compare
-Wsuggest-override \ -Wstringop-overflow=4
-Wswitch \ -Wstringop-overread
-Wswitch-bool \ -Wstringop-truncation
-Wswitch-default \ -Wsubobject-linkage
-Wswitch-enum \ -Wsuggest-attribute=cold
-Wswitch-outside-range \ -Wsuggest-attribute=const
-Wswitch-unreachable \ -Wsuggest-attribute=format
-Wsync-nand \ -Wsuggest-attribute=malloc
-Wsynth \ -Wsuggest-attribute=noreturn
-Wno-system-headers \ -Wsuggest-attribute=pure
-Wtautological-compare \ -Wsuggest-final-methods
-Wno-templates \ -Wsuggest-final-types
-Wterminate \ -Wsuggest-override
-Wtrampolines \ -Wswitch
-Wtrigraphs \ -Wswitch-bool
-Wtsan \ -Wswitch-default
-Wtype-limits \ -Wswitch-enum
-Wundef \ -Wswitch-outside-range
-Wuninitialized \ -Wswitch-unreachable
-Wunknown-pragmas \ -Wsync-nand
-Wunreachable-code \ -Wsynth
-Wunsafe-loop-optimizations \ -Wno-system-headers
-Wunused \ -Wtautological-compare
-Wunused-but-set-parameter \ -Wno-templates
-Wunused-but-set-variable \ -Wterminate
-Wunused-const-variable=2 \ -Wtrampolines
-Wunused-function \ -Wtrigraphs
-Wunused-label \ -Wtsan
-Wunused-local-typedefs \ -Wtype-limits
-Wunused-macros \ -Wundef
-Wunused-parameter \ -Wuninitialized
-Wunused-result \ -Wunknown-pragmas
-Wunused-value \ -Wunreachable-code
-Wunused-variable \ -Wunsafe-loop-optimizations
-Wuseless-cast \ -Wunused
-Wvarargs \ -Wunused-but-set-parameter
-Wvariadic-macros \ -Wunused-but-set-variable
-Wvector-operation-performance \ -Wunused-const-variable=2
-Wvexing-parse \ -Wunused-function
-Wvirtual-inheritance \ -Wunused-label
-Wvirtual-move-assign \ -Wunused-local-typedefs
-Wvla \ -Wunused-macros
-Wvla-parameter \ -Wunused-parameter
-Wvolatile \ -Wunused-result
-Wvolatile-register-var \ -Wunused-value
-Wwrite-strings \ -Wunused-variable
-Wzero-as-null-pointer-constant \ -Wuseless-cast
-Wzero-length-bounds \ -Wvarargs
") -Wvariadic-macros
-Wvector-operation-performance
-Wvexing-parse
-Wvirtual-inheritance
-Wvirtual-move-assign
-Wvla
-Wvla-parameter
-Wvolatile
-Wvolatile-register-var
-Wwrite-strings
-Wzero-as-null-pointer-constant
-Wzero-length-bounds
)
add_custom_target(ci_test_gcc add_custom_target(ci_test_gcc
COMMAND CXX=${GCC_TOOL} CXXFLAGS=${GCC_CXXFLAGS} ${CMAKE_COMMAND} COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc
@ -406,7 +419,7 @@ add_custom_target(ci_test_gcc
) )
add_custom_target(ci_test_clang add_custom_target(ci_test_clang
COMMAND CXX=${CLANG_TOOL} CXXFLAGS=${CLANG_CXXFLAGS} ${CMAKE_COMMAND} COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang
@ -421,10 +434,10 @@ add_custom_target(ci_test_clang
foreach(CXX_STANDARD 11 14 17 20) foreach(CXX_STANDARD 11 14 17 20)
add_custom_target(ci_test_gcc_cxx${CXX_STANDARD} add_custom_target(ci_test_gcc_cxx${CXX_STANDARD}
COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND} COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_BUILD_TYPE=Debug -GNinja
-DCMAKE_CXX_STANDARD=${CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_BuildTests=ON -DJSON_FastTests=ON
-DJSON_TestStandards=${CXX_STANDARD}
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD}
COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
@ -432,10 +445,10 @@ foreach(CXX_STANDARD 11 14 17 20)
) )
add_custom_target(ci_test_clang_cxx${CXX_STANDARD} add_custom_target(ci_test_clang_cxx${CXX_STANDARD}
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_BUILD_TYPE=Debug -GNinja
-DCMAKE_CXX_STANDARD=${CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON -DJSON_BuildTests=ON -DJSON_FastTests=ON
-DJSON_BuildTests=ON -DJSON_TestStandards=${CXX_STANDARD}
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
@ -756,50 +769,67 @@ add_custom_target(ci_benchmarks
# CMake flags # CMake flags
############################################################################### ###############################################################################
if (APPLE) function(ci_get_cmake version var)
set(CMAKE_310_BINARY ${PROJECT_BINARY_DIR}/cmake-3.1.0-Darwin64/CMake.app/Contents/bin/cmake) if (APPLE)
add_custom_command( set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}-Darwin64/CMake.app/Contents/bin/cmake)
OUTPUT ${CMAKE_310_BINARY} add_custom_command(
COMMAND wget https://github.com/Kitware/CMake/releases/download/v3.1.0/cmake-3.1.0-Darwin64.tar.gz OUTPUT ${${var}}
COMMAND tar xfz cmake-3.1.0-Darwin64.tar.gz COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-Darwin64.tar.gz
COMMAND rm cmake-3.1.0-Darwin64.tar.gz COMMAND tar xfz cmake-${version}-Darwin64.tar.gz
WORKING_DIRECTORY ${PROJECT_BINARY_DIR} COMMAND rm cmake-${version}-Darwin64.tar.gz
COMMENT "Download CMake 3.1.0" WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
) COMMENT "Download CMake ${version}"
else() )
set(CMAKE_310_BINARY ${PROJECT_BINARY_DIR}/cmake-3.1.0-Linux-x86_64/bin/cmake) else()
add_custom_command( set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}-Linux-x86_64/bin/cmake)
OUTPUT ${CMAKE_310_BINARY} add_custom_command(
COMMAND wget https://github.com/Kitware/CMake/releases/download/v3.1.0/cmake-3.1.0-Linux-x86_64.tar.gz OUTPUT ${${var}}
COMMAND tar xfz cmake-3.1.0-Linux-x86_64.tar.gz COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-Linux-x86_64.tar.gz
COMMAND rm cmake-3.1.0-Linux-x86_64.tar.gz COMMAND tar xfz cmake-${version}-Linux-x86_64.tar.gz
WORKING_DIRECTORY ${PROJECT_BINARY_DIR} COMMAND rm cmake-${version}-Linux-x86_64.tar.gz
COMMENT "Download CMake 3.1.0" WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
) COMMENT "Download CMake ${version}"
endif() )
endif()
set(${var} ${${var}} PARENT_SCOPE)
endfunction()
set(JSON_CMAKE_FLAGS "JSON_BuildTests;JSON_Install;JSON_MultipleHeaders;JSON_ImplicitConversions;JSON_Valgrind;JSON_Diagnostics;JSON_SystemInclude") ci_get_cmake(3.1.0 CMAKE_3_1_0_BINARY)
ci_get_cmake(3.13.0 CMAKE_3_13_0_BINARY)
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS}) set(JSON_CMAKE_FLAGS_3_1_0 "JSON_Install;JSON_MultipleHeaders;JSON_ImplicitConversions;JSON_Valgrind;JSON_Diagnostics;JSON_SystemInclude")
string(TOLOWER "ci_cmake_flag_${JSON_CMAKE_FLAG}" JSON_CMAKE_FLAG_TARGET) set(JSON_CMAKE_FLAGS_3_13_0 "JSON_BuildTests")
add_custom_target("${JSON_CMAKE_FLAG_TARGET}"
COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${CMAKE_VERSION})" function(ci_add_cmake_flags_targets flag min_version)
string(TOLOWER "ci_cmake_flag_${flag}" flag_target)
string(REPLACE . _ min_version_var ${min_version})
set(cmake_binary ${CMAKE_${min_version_var}_BINARY})
add_custom_target(${flag_target}
COMMENT "Check CMake flag ${flag} (CMake ${CMAKE_VERSION})"
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
-Werror=dev -Werror=dev
-D${JSON_CMAKE_FLAG}=ON -D${flag}=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET} -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target}
) )
add_custom_target("${JSON_CMAKE_FLAG_TARGET}_31" add_custom_target(${flag_target}_${min_version_var}
COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake 3.1)" COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${min_version})"
COMMAND mkdir ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31 COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
COMMAND cd ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31 && ${CMAKE_310_BINARY} COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
-Werror=dev ${PROJECT_SOURCE_DIR} && ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON
-D${JSON_CMAKE_FLAG}=ON DEPENDS ${cmake_binary}
-DCMAKE_CXX_COMPILE_FEATURES="cxx_range_for" -DCMAKE_CXX_FLAGS="-std=gnu++11"
DEPENDS ${CMAKE_310_BINARY}
) )
list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${JSON_CMAKE_FLAG_TARGET}_31) list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${flag_target}_${min_version_var})
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET} ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31) list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target} ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var})
set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE)
set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE)
endfunction()
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_1_0})
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.1.0)
endforeach()
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_13_0})
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.13.0)
endforeach() endforeach()
add_custom_target(ci_cmake_flags add_custom_target(ci_cmake_flags

204
cmake/test.cmake Normal file
View File

@ -0,0 +1,204 @@
set(_json_test_cmake_list_file ${CMAKE_CURRENT_LIST_FILE})
#############################################################################
# download test data
#############################################################################
include(download_test_data)
# test fixture to download test data
add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
--target download_test_data
)
set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA)
if(JSON_Valgrind)
find_program(CMAKE_MEMORYCHECK_COMMAND valgrind)
message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})")
set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full")
separate_arguments(memcheck_command)
endif()
#############################################################################
# detect standard support
#############################################################################
# C++11 is the minimum required
set(compiler_supports_cpp_11 TRUE)
foreach(feature ${CMAKE_CXX_COMPILE_FEATURES})
if (${feature} STREQUAL cxx_std_14)
set(compiler_supports_cpp_14 TRUE)
elseif (${feature} STREQUAL cxx_std_17)
set(compiler_supports_cpp_17 TRUE)
elseif (${feature} STREQUAL cxx_std_20)
set(compiler_supports_cpp_20 TRUE)
elseif (${feature} STREQUAL cxx_std_23)
set(compiler_supports_cpp_23 TRUE)
endif()
endforeach()
#############################################################################
# test functions
#############################################################################
#############################################################################
# json_test_set_test_options(
# all|<tests>
# [CXX_STANDARDS all|<args>...]
# [COMPILE_DEFINITIONS <args>...]
# [COMPILE_FEATURES <args>...]
# [COMPILE_OPTIONS <args>...]
# [LINK_LIBRARIES <args>...]
# [LINK_OPTIONS <args>...])
#
# Supply test- and standard-specific build settings.
# Specify multiple tests using a list e.g., "test-foo;test-bar".
#
# Must be called BEFORE the test is created.
#############################################################################
function(json_test_set_test_options tests)
cmake_parse_arguments(args "" ""
"CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS"
${ARGN})
if(NOT args_CXX_STANDARDS)
set(args_CXX_STANDARDS "all")
endif()
foreach(test ${tests})
if("${test}" STREQUAL "all")
set(test "")
endif()
foreach(cxx_standard ${args_CXX_STANDARDS})
if("${cxx_standard}" STREQUAL "all")
if("${test}" STREQUAL "")
message(FATAL_ERROR "Not supported. Change defaults in: ${_json_test_cmake_list_file}")
endif()
set(test_interface _json_test_interface_${test})
else()
set(test_interface _json_test_interface_${test}_cpp_${cxx_standard})
endif()
if(NOT TARGET ${test_interface})
add_library(${test_interface} INTERFACE)
endif()
target_compile_definitions(${test_interface} INTERFACE ${args_COMPILE_DEFINITIONS})
target_compile_features(${test_interface} INTERFACE ${args_COMPILE_FEATURES})
target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS})
target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES})
target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS})
endforeach()
endforeach()
endfunction()
# for internal use by json_test_add_test_for()
function(_json_test_add_test test_name file main cxx_standard)
set(test_target ${test_name}_cpp${cxx_standard})
if(TARGET ${test_target})
message(FATAL_ERROR "Target ${test_target} has already been added.")
endif()
add_executable(${test_target} ${file})
target_link_libraries(${test_target} PRIVATE ${main})
# set and require C++ standard
set_target_properties(${test_target} PROPERTIES
CXX_STANDARD ${cxx_standard}
CXX_STANDARD_REQUIRED ON
)
# apply standard-specific build settings
if(TARGET _json_test_interface__cpp_${cxx_standard})
target_link_libraries(${test_target} PRIVATE _json_test_interface__cpp_${cxx_standard})
endif()
# apply test-specific build settings
if(TARGET _json_test_interface_${test_name})
target_link_libraries(${test_target} PRIVATE _json_test_interface_${test_name})
endif()
# apply test- and standard-specific build settings
if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
target_link_libraries(${test_target} PRIVATE
_json_test_interface_${test_name}_cpp_${cxx_standard}
)
endif()
if (JSON_FastTests)
add_test(NAME ${test_target}
COMMAND ${test_target} ${DOCTEST_TEST_FILTER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
else()
add_test(NAME ${test_target}
COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
if(JSON_Valgrind)
add_test(NAME ${test_target}_valgrind
COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
set_tests_properties(${test_target}_valgrind PROPERTIES
LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA
)
endif()
endfunction()
#############################################################################
# json_test_add_test_for(
# <file>
# MAIN <main>
# [CXX_STANDARDS <version_number>...] [FORCE])
#
# Given a <file> unit-foo.cpp, produces
#
# test-foo_cpp<version_number>
#
# if C++ standard <version_number> is supported by the compiler and the
# source file contains JSON_HAS_CPP_<version_number>.
# Use FORCE to create the test regardless of the file containing
# JSON_HAS_CPP_<version_number>.
# Test targets are linked against <main>.
# CXX_STANDARDS defaults to "11".
#############################################################################
function(json_test_add_test_for file)
cmake_parse_arguments(args "FORCE" "MAIN" "CXX_STANDARDS" ${ARGN})
get_filename_component(file_basename ${file} NAME_WE)
string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename})
if("${args_MAIN}" STREQUAL "")
message(FATAL_ERROR "Required argument MAIN <main> missing.")
endif()
if("${args_CXX_STANDARDS}" STREQUAL "")
set(args_CXX_STANDARDS 11)
endif()
file(READ ${file} file_content)
foreach(cxx_standard ${args_CXX_STANDARDS})
if(NOT compiler_supports_cpp_${cxx_standard})
continue()
endif()
# add unconditionally if C++11 (default) or forced
if(NOT ("${cxx_standard}" STREQUAL 11 OR args_FORCE))
string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found)
if(${has_cpp_found} EQUAL -1)
continue()
endif()
endif()
_json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard})
endforeach()
endfunction()

View File

@ -43,6 +43,10 @@ Linear.
--8<-- "examples/operator_literal_json_pointer.output" --8<-- "examples/operator_literal_json_pointer.output"
``` ```
## See also
- [json_pointer](../json_pointer/index.md) - type to represent JSON Pointers
## Version history ## Version history
- Added in version 2.0.0. - Added in version 2.0.0.

View File

@ -29,6 +29,7 @@ are the base for JSON patches.
## See also ## See also
- [operator""_json_pointer](../basic_json/operator_literal_json_pointer.md) - user-defined string literal for JSON pointers
- [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901) - [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901)
## Version history ## Version history

View File

@ -85,29 +85,31 @@ Some important things:
If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate. If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate.
There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object: There are four macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for. - `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. - `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. In all macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. You can read more docs about them starting from [here](macros.md#nlohmann_define_type_intrusivetype-member).
!!! note !!! note
At most 64 member variables can be passed to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` or `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. At most 64 member variables can be passed to these macros.
??? example ??? example
The `to_json`/`from_json` functions for the `person` struct above can be created with: The `to_json`/`from_json` functions for the `person` struct above can be created with:
```cpp ```cpp
namespace ns { namespace ns {
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
} }
``` ```
Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed: Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed:
```cpp ```cpp
namespace ns { namespace ns {
class address { class address {
@ -115,7 +117,7 @@ In both macros, the first parameter is the name of the class/struct, and all rem
std::string street; std::string street;
int housenumber; int housenumber;
int postcode; int postcode;
public: public:
NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode) NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
}; };

View File

@ -1,19 +1,123 @@
# JSON Pointer # JSON Pointer
The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. ## Introduction
The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address
structured values. A JSON Pointer is a string that identifies a specific value withing a JSON document.
Consider the following JSON document
```json
{
"array": ["A", "B", "C"],
"nested": {
"one": 1,
"two": 2,
"three": [true, false]
}
}
```
Then every value inside the JSON document can be idientified as follows:
| JSON Pointer | JSON value |
|-------------------|----------------------------------------------------------------------------------|
| `/` | `#!json {"array":["A","B","C"],"nested":{"one":1,"two":2,"three":[true,false]}}` |
| `/array` | `#!json ["A","B","C"]` |
| `/array/0` | `#!json A` |
| `/array/1` | `#!json B` |
| `/array/2` | `#!json C` |
| `/nested` | `#!json {"one":1,"two":2,"three":[true,false]}` |
| `/nested/one` | `#!json 1` |
| `/nested/two` | `#!json 2` |
| `/nested/three` | `#!json [true,false]` |
| `/nested/three/0` | `#!json true` |
| `/nested/three/1` | `#!json false` |
## JSON Pointer creation
JSON Pointers can be created from a string:
```cpp ```cpp
// a JSON value json::json_pointer p = "/nested/one";
json j_original = R"({ ```
"baz": ["one", "two", "three"],
"foo": "bar"
})"_json;
// access members with a JSON pointer (RFC 6901) Furthermore, a user-defined string literal can be used to achieve the same result:
j_original["/baz/1"_json_pointer];
// "two" ```cpp
auto p = "/nested/one"_json_pointer;
```
The escaping rules of [RFC 6901](https://tools.ietf.org/html/rfc6901) are implemented. See the
[constructor documentation](../api/json_pointer/json_pointer.md) for more information.
## Value access
JSON Pointers can be used in the [`at`](../api/basic_json/at.md), [`operator[]`](../api/basic_json/operator%5B%5D.md),
and [`value`](../api/basic_json/value.md) functions just like object keys or array indices.
```cpp
// the JSON value from above
auto j = json::parse(R"({
"array": ["A", "B", "C"],
"nested": {
"one": 1,
"two": 2,
"three": [true, false]
}
})");
// access values
auto val = j["/"_json_pointer]; // {"array":["A","B","C"],...}
auto val1 = j["/nested/one"_json_pointer]; // 1
auto val2 = j.at[json::json_pointer("/nested/three/1")]; // false
auto val3 = j.value[json::json_pointer("/nested/four", 0)]; // 0
```
## Flatten / unflatten
The library implements a function [`flatten`](../api/basic_json/flatten.md) to convert any JSON document into a JSON
object where each key is a JSON Pointer and each value is a primitive JSON value (i.e., a string, boolean, number, or
null).
```cpp
// the JSON value from above
auto j = json::parse(R"({
"array": ["A", "B", "C"],
"nested": {
"one": 1,
"two": 2,
"three": [true, false]
}
})");
// create flattened value
auto j_flat = j.flatten();
```
The resulting value `j_flat` is:
```json
{
"/array/0": "A",
"/array/1": "B",
"/array/2": "C",
"/nested/one": 1,
"/nested/two": 2,
"/nested/three/0": true,
"/nested/three/1": false
}
```
The reverse function, [`unflatten`](../api/basic_json/unflatten.md) recreates the original value.
```cpp
auto j_original = j_flat.unflatten();
``` ```
## See also ## See also
- Class [`json_pointer`](../api/json_pointer/index.md) - Class [`json_pointer`](../api/json_pointer/index.md)
- Function [`flatten`](../api/basic_json/flatten.md)
- Function [`unflatten`](../api/basic_json/unflatten.md)
- [JSON Patch](json_patch.md)

View File

@ -4,16 +4,41 @@ Some aspects of the library can be configured by defining preprocessor macros be
## `JSON_ASSERT(x)` ## `JSON_ASSERT(x)`
The default value is `#!cpp assert(x)`. This macro controls which code is executed for runtime assertions of the libraries.
!!! info "Default behavior"
The default value is [`#!cpp assert(x)`](https://en.cppreference.com/w/cpp/error/assert).
```cpp
#define JSON_ASSERT(x) assert(x)
```
## `JSON_CATCH_USER(exception)` ## `JSON_CATCH_USER(exception)`
This macro overrides `#!cpp catch` calls inside the library. The argument is the type of the exception to catch. As of This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library.
version 3.8.0, the library only catches `std::out_of_range` exceptions internally to rethrow them as The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range`
[`json::out_of_range`](../home/exceptions.md#out-of-range) exceptions. The macro is always followed by a scope. exceptions internally to rethrow them as [`json::out_of_range`](../home/exceptions.md#out-of-range) exceptions. The
macro is always followed by a scope.
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example. See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
!!! info "Default behavior"
When exceptions are enabled, the default value is
[`#!cpp catch(exception)`](https://en.cppreference.com/w/cpp/language/try_catch).
```cpp
#define JSON_CATCH_USER(exception) catch(exception)
```
When exceptions are switched off by the compiler, the default value is `#!cpp if (false)` to make the catch block
unreachable.
```cpp
#define JSON_CATCH_USER(exception) if (false)
```
## `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
@ -26,6 +51,18 @@ that enabling this macro increases the size of every JSON value by one pointer a
The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets
`JSON_DIAGNOSTICS` accordingly. `JSON_DIAGNOSTICS` accordingly.
!!! warning
As this macro changes the definition of the `basic_json` object, it MUST be defined in the same way globally, even
across different compilation units; DO NOT link together code compiled with different definitions of
`JSON_DIAGNOSTICS` as this is a violation of the One Definition Rule and will cause undefined behaviour.
!!! info "Default behavior"
```cpp
#define JSON_DIAGNOSTICS 0
```
## `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, `JSON_HAS_CPP_20` ## `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, `JSON_HAS_CPP_20`
The library targets C++11, but also supports some features introduced in later C++ versions (e.g., `std::string_view` The library targets C++11, but also supports some features introduced in later C++ versions (e.g., `std::string_view`
@ -34,6 +71,11 @@ standard. By defining any of these symbols, the internal check is overridden and
unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be
detected incorrectly. detected incorrectly.
!!! info "Default behavior"
The default value is detected based on the preprocessor macros `#!cpp __cplusplus`, `#!cpp _HAS_CXX17`, or
`#!cpp _MSVC_LANG`.
## `JSON_HAS_FILESYSTEM`, `JSON_HAS_EXPERIMENTAL_FILESYSTEM` ## `JSON_HAS_FILESYSTEM`, `JSON_HAS_EXPERIMENTAL_FILESYSTEM`
When compiling with C++17, the library provides conversions from and to `std::filesystem::path`. As compiler support When compiling with C++17, the library provides conversions from and to `std::filesystem::path`. As compiler support
@ -41,12 +83,29 @@ for filesystem is limited, the library tries to detect whether `<filesystem>`/`s
or `<experimental/filesystem>`/`std::experimental::filesystem` (`JSON_HAS_EXPERIMENTAL_FILESYSTEM`) should be used. or `<experimental/filesystem>`/`std::experimental::filesystem` (`JSON_HAS_EXPERIMENTAL_FILESYSTEM`) should be used.
To override the built-in check, define `JSON_HAS_FILESYSTEM` or `JSON_HAS_EXPERIMENTAL_FILESYSTEM` to `1`. To override the built-in check, define `JSON_HAS_FILESYSTEM` or `JSON_HAS_EXPERIMENTAL_FILESYSTEM` to `1`.
!!! info "Default behavior"
The default value is detected based on the preprocessor macros `#!cpp __cpp_lib_filesystem`,
`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include(<filesystem>)`, or
`#!cpp __has_include(<experimental/filesystem>)`.
Note that older compilers or older versions of libstd++ also require the library `stdc++fs` to be linked to for
filesystem support.
## `JSON_NOEXCEPTION` ## `JSON_NOEXCEPTION`
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. When defining `JSON_NOEXCEPTION`, `#!cpp try` Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. When defining `JSON_NOEXCEPTION`, `#!cpp try`
is replaced by `#!cpp if (true)`, `#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by is replaced by `#!cpp if (true)`, `#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by
`#!cpp std::abort()`. `#!cpp std::abort()`.
!!! info "Default behavior"
By default, the macro is not defined.
```cpp
#undef JSON_NOEXCEPTION
```
The same effect is achieved by setting the compiler flag `-fno-exceptions`. The same effect is achieved by setting the compiler flag `-fno-exceptions`.
Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not
@ -58,23 +117,72 @@ When defined, headers `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostrea
relying on these headers are excluded. This is relevant for environment where these I/O functions are disallowed for relying on these headers are excluded. This is relevant for environment where these I/O functions are disallowed for
security reasons (e.g., Intel Software Guard Extensions (SGX)). security reasons (e.g., Intel Software Guard Extensions (SGX)).
!!! info "Default behavior"
By default, the macro is not defined.
```cpp
#undef JSON_NO_IO
```
## `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK` ## `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`
When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to
use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used. use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used.
!!! info "Default behavior"
By default, the macro is not defined.
```cpp
#undef JSON_SKIP_UNSUPPORTED_COMPILER_CHECK
```
## `JSON_THROW_USER(exception)` ## `JSON_THROW_USER(exception)`
This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. Note that This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. Note that
`JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield
undefined behavior. undefined behavior.
!!! info "Default behavior"
When exceptions are enabled, the default value is
[`#!cpp throw exception`](https://en.cppreference.com/w/cpp/language/throw).
```cpp
#define JSON_THROW_USER(exception) throw exception
```
When exceptions are switched off by the compiler, the default value is
[`#!cpp std::abort()`](https://en.cppreference.com/w/cpp/utility/program/abort) to make reaching the throw branch
abort the process.
```cpp
#define JSON_THROW_USER(exception) std::abort()
```
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example. See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
## `JSON_TRY_USER` ## `JSON_TRY_USER`
This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope. This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope.
!!! info "Default behavior"
When exceptions are enabled, the default value is
[`#!cpp try`](https://en.cppreference.com/w/cpp/language/try_catch).
```cpp
#define JSON_TRY_USER try
```
When exceptions are switched off by the compiler, the default value is `#!cpp if (true)` to unconditionally execute
the following code block.
```cpp
#define JSON_TRY_USER if (true)
```
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example. See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
## `JSON_USE_IMPLICIT_CONVERSIONS` ## `JSON_USE_IMPLICIT_CONVERSIONS`
@ -84,12 +192,12 @@ When defined to `0`, implicit conversions are switched off. By default, implicit
??? example ??? example
This is an example for an implicit conversion: This is an example for an implicit conversion:
```cpp ```cpp
json j = "Hello, world!"; json j = "Hello, world!";
std::string s = j; std::string s = j;
``` ```
When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be
written like this: written like this:
@ -101,6 +209,12 @@ When defined to `0`, implicit conversions are switched off. By default, implicit
Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which
sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly. sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly.
!!! info "Default behavior"
```cpp
#define JSON_USE_IMPLICIT_CONVERSIONS 1
```
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)` ## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)`
This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as
@ -112,6 +226,10 @@ The first parameter is the name of the class/struct, and all remaining parameter
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)`
This macro is similar to `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)` ## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)`
This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as
@ -123,6 +241,10 @@ first parameter is the name of the class/struct, and all remaining parameters na
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)`
This macro is similar to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.
## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` ## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)`
This macro simplifies the serialization/deserialization of enum types. See This macro simplifies the serialization/deserialization of enum types. See

View File

@ -2,6 +2,8 @@
The [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs". As such, an implementation does not need to preserve any specific order of object keys. The [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs". As such, an implementation does not need to preserve any specific order of object keys.
## Default behavior: sort keys
The default type `nlohmann::json` uses a `std::map` to store JSON objects, and thus stores object keys **sorted alphabetically**. The default type `nlohmann::json` uses a `std::map` to store JSON objects, and thus stores object keys **sorted alphabetically**.
??? example ??? example
@ -33,6 +35,8 @@ The default type `nlohmann::json` uses a `std::map` to store JSON objects, and t
} }
``` ```
## Alternative behavior: preserve insertion order
If you do want to preserve the **insertion order**, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179). If you do want to preserve the **insertion order**, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179).
??? example ??? example
@ -65,3 +69,58 @@ If you do want to preserve the **insertion order**, you can try the type [`nlohm
``` ```
Alternatively, you can use a more sophisticated ordered map like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)). Alternatively, you can use a more sophisticated ordered map like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
### Notes on parsing
Note that you also need to call the right [`parse`](../api/basic_json/parse.md) function when reading from a file.
Assume file `input.json` contains the JSON object above:
```json
{
"one": 1,
"two": 2,
"three": 3
}
```
!!! success "Right way"
The following code correctly calls the `parse` function from `nlohmann::ordered_json`:
```cpp
std::ifstream i("input.json");
auto j = nlohmann::ordered_json::parse(i);
std::cout << j.dump(2) << std::endl;
```
The output will be:
```json
{
"one": 1,
"two": 2,
"three": 3
}
```
??? failure "Wrong way"
The following code incorrectly calls the `parse` function from `nlohmann::json` which does not preserve the
insertion order, but sorts object keys. Assigning the result to `nlohmann::ordered_json` compiles, but does not
restore the order from the input file.
```cpp
std::ifstream i("input.json");
nlohmann::ordered_json j = nlohmann::json::parse(i);
std::cout << j.dump(2) << std::endl;
```
The output will be:
```json
{
"one": 1,
"three": 3
"two": 2,
}
```

View File

@ -2,102 +2,126 @@
## Integration ## Integration
You can also 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. 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 ### 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: 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:
```cmake !!! example
# CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo 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. ```cmake title="CMakeLists.txt"
cmake_minimum_required(VERSION 3.1)
project(ExampleProject LANGUAGES CXX)
find_package(nlohmann_json 3.10.5 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 ### 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: 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.
```cmake !!! example
# 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 "")
# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it ```cmake title="CMakeLists.txt"
# unintended consequences that will break the build. It's generally cmake_minimum_required(VERSION 3.1)
# discouraged (although not necessarily well documented as such) to use project(ExampleProject LANGUAGES CXX)
# include(...) for pulling in other CMake projects anyways.
add_subdirectory(nlohmann_json)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
### Embedded (FetchContent) # 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)
Since CMake v3.11, add_executable(example example.cpp)
[FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json)
be used to automatically download the repository as a dependency at configure type. ```
Example: !!! note
```cmake
include(FetchContent)
FetchContent_Declare(json Do not use `#!cmake include(nlohmann_json/CMakeLists.txt)`, since that carries with it unintended consequences that
GIT_REPOSITORY https://github.com/nlohmann/json will break the build. It is generally discouraged (although not necessarily well documented as such) to use
GIT_TAG v3.7.3) `#!cmake include(...)` for pulling in other CMake projects anyways.
FetchContent_GetProperties(json)
if(NOT json_POPULATED)
FetchContent_Populate(json)
add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
!!! Note
The repository <https://github.com/nlohmann/json> download size is quite large.
You might want to depend on a smaller repository. For instance, you might want to replace the URL above by
<https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent>.
### Supporting Both ### 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: To allow your project to support either an externally supplied or an embedded JSON library, you can use a pattern akin
to the following.
``` cmake !!! example
# Top level CMakeLists.txt
project(FOO)
...
option(FOO_USE_EXTERNAL_JSON "Use an external JSON library" OFF)
...
add_subdirectory(thirdparty)
...
add_library(foo ...)
...
# Note that the namespaced target will always be available regardless of the
# import method
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
```
```cmake
# thirdparty/CMakeLists.txt
...
if(FOO_USE_EXTERNAL_JSON)
find_package(nlohmann_json 3.2.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. ```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.10.5 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 type.
!!! 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.10.5/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.10.5
)
```
However, the repository <https://github.com/nlohmann/json> download size is quite large. You might want to depend on
a smaller repository. For instance, you might want to replace the URL in the example by
<https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent>.
## CMake Options ## CMake Options

View File

@ -1,9 +1,10 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <iostream> #include <iostream>
#include <iomanip>
using json = nlohmann::json; using json = nlohmann::json;
int main() int main()
{ {
std::cout << json::meta() << std::endl; std::cout << std::setw(4) << json::meta() << std::endl;
} }

View File

@ -1,6 +1,7 @@
# Header only # Header only
[`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is the single required file in `single_include/nlohmann` or [released here](https://github.com/nlohmann/json/releases). You need to add [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is the single required
file in `single_include/nlohmann` or [released here](https://github.com/nlohmann/json/releases). You need to add
```cpp ```cpp
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
@ -9,6 +10,9 @@
using json = nlohmann::json; using json = nlohmann::json;
``` ```
to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and
Clang).
You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp) for forward-declarations. The installation of `json_fwd.hpp` (as part of CMake's install step), can be achieved by setting `-DJSON_MultipleHeaders=ON`. You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp)
for forward-declarations. The installation of `json_fwd.hpp` (as part of CMake's install step), can be achieved by
setting `-DJSON_MultipleHeaders=ON`.

View File

@ -6,6 +6,12 @@ Throughout this page, we will describe how to compile the example file `example.
--8<-- "integration/example.cpp" --8<-- "integration/example.cpp"
``` ```
When executed, this program should create output similar to
```json
--8<-- "../../examples/meta.output"
```
## Homebrew ## Homebrew
If you are using OS X and [Homebrew](http://brew.sh), just type If you are using OS X and [Homebrew](http://brew.sh), just type
@ -26,11 +32,9 @@ instead. See [nlohmann-json](https://formulae.brew.sh/formula/nlohmann-json) for
1. Create the following file: 1. Create the following file:
=== "example.cpp" ```cpp title="example.cpp"
--8<-- "integration/example.cpp"
```cpp ```
--8<-- "integration/example.cpp"
```
2. Install the package 2. Install the package
@ -50,6 +54,8 @@ instead. See [nlohmann-json](https://formulae.brew.sh/formula/nlohmann-json) for
clang++ example.cpp -I/usr/local/Cellar/nlohmann-json/3.7.3/include -std=c++11 -o example clang++ example.cpp -I/usr/local/Cellar/nlohmann-json/3.7.3/include -std=c++11 -o example
``` ```
:material-update: The [formula](https://formulae.brew.sh/formula/nlohmann-json) is updated automatically.
## Meson ## Meson
If you are using the [Meson Build System](http://mesonbuild.com), add this source tree as a [meson subproject](https://mesonbuild.com/Subprojects.html#using-a-subproject). You may also use the `include.zip` published in this project's [Releases](https://github.com/nlohmann/json/releases) to reduce the size of the vendored source tree. Alternatively, you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/nlohmann_json), or simply use `meson wrap install nlohmann_json`. Please see the meson project for any issues regarding the packaging. If you are using the [Meson Build System](http://mesonbuild.com), add this source tree as a [meson subproject](https://mesonbuild.com/Subprojects.html#using-a-subproject). You may also use the `include.zip` published in this project's [Releases](https://github.com/nlohmann/json/releases) to reduce the size of the vendored source tree. Alternatively, you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/nlohmann_json), or simply use `meson wrap install nlohmann_json`. Please see the meson project for any issues regarding the packaging.
@ -64,24 +70,17 @@ If you are using [Conan](https://www.conan.io/) to manage your dependencies, mer
1. Create the following files: 1. Create the following files:
=== "Conanfile.txt" ```ini title="Conanfile.txt"
--8<-- "integration/conan/Conanfile.txt"
```ini ```
--8<-- "integration/conan/Conanfile.txt"
```
=== "CMakeLists.txt" ```cmake title="CMakeLists.txt"
--8<-- "integration/conan/CMakeLists.txt"
```cmake ```
--8<-- "integration/conan/CMakeLists.txt"
```
=== "example.cpp"
```cpp
--8<-- "integration/conan/example.cpp"
```
```cpp title="example.cpp"
--8<-- "integration/conan/example.cpp"
```
2. Build: 2. Build:
@ -93,6 +92,8 @@ If you are using [Conan](https://www.conan.io/) to manage your dependencies, mer
cmake --build . cmake --build .
``` ```
:material-update: The [package](https://conan.io/center/nlohmann_json) is updated automatically.
## Spack ## Spack
If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the [`nlohmann-json` package](https://spack.readthedocs.io/en/latest/package_list.html#nlohmann-json). Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging. If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the [`nlohmann-json` package](https://spack.readthedocs.io/en/latest/package_list.html#nlohmann-json). Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging.
@ -113,17 +114,13 @@ If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project fo
1. Create the following files: 1. Create the following files:
=== "CMakeLists.txt" ```cmake title="CMakeLists.txt"
--8<-- "integration/vcpkg/CMakeLists.txt"
```cmake ```
--8<-- "integration/vcpkg/CMakeLists.txt"
``` ```cpp title="example.cpp"
--8<-- "integration/vcpkg/example.cpp"
=== "example.cpp" ```
```cpp
--8<-- "integration/vcpkg/example.cpp"
```
2. Install package: 2. Install package:
@ -146,6 +143,8 @@ If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project fo
If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`). If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`).
:material-update: cget reads directly from the [GitHub repository](https://github.com/nlohmann/json) and is always up-to-date.
## CocoaPods ## CocoaPods
If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open). If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open).
@ -162,19 +161,27 @@ If you are using [conda](https://conda.io/), you can use the package [nlohmann_j
If you are using [MSYS2](http://www.msys2.org/), you can use the [mingw-w64-nlohmann-json](https://packages.msys2.org/base/mingw-w64-nlohmann-json) package, just type `pacman -S mingw-w64-i686-nlohmann-json` or `pacman -S mingw-w64-x86_64-nlohmann-json` for installation. Please file issues [here](https://github.com/msys2/MINGW-packages/issues/new?title=%5Bnlohmann-json%5D) if you experience problems with the packages. If you are using [MSYS2](http://www.msys2.org/), you can use the [mingw-w64-nlohmann-json](https://packages.msys2.org/base/mingw-w64-nlohmann-json) package, just type `pacman -S mingw-w64-i686-nlohmann-json` or `pacman -S mingw-w64-x86_64-nlohmann-json` for installation. Please file issues [here](https://github.com/msys2/MINGW-packages/issues/new?title=%5Bnlohmann-json%5D) if you experience problems with the packages.
:material-update: The [package](https://packages.msys2.org/base/mingw-w64-nlohmann-json) is updated automatically.
## MacPorts ## MacPorts
If you are using [MacPorts](https://ports.macports.org), execute `sudo port install nlohmann-json` to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) package. If you are using [MacPorts](https://ports.macports.org), execute `sudo port install nlohmann-json` to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) package.
:material-update: The [package](https://ports.macports.org/port/nlohmann-json/) is updated automatically.
## build2 ## build2
If you are using [`build2`](https://build2.org), you can use the [`nlohmann-json`](https://cppget.org/nlohmann-json) package from the public repository http://cppget.org or directly from the [package's sources repository](https://github.com/build2-packaging/nlohmann-json). In your project's `manifest` file, just add `depends: nlohmann-json` (probably with some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps)). If you are not familiar with using dependencies in `build2`, [please read this introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml). If you are using [`build2`](https://build2.org), you can use the [`nlohmann-json`](https://cppget.org/nlohmann-json) package from the public repository <http://cppget.org> or directly from the [package's sources repository](https://github.com/build2-packaging/nlohmann-json). In your project's `manifest` file, just add `depends: nlohmann-json` (probably with some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps)). If you are not familiar with using dependencies in `build2`, [please read this introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml).
Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if you experience problems with the packages. Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if you experience problems with the packages.
:material-update: The [package](https://cppget.org/nlohmann-json) is updated automatically.
## wsjcpp ## wsjcpp
If you are using [`wsjcpp`](http://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch. If you are using [`wsjcpp`](http://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch.
:material-update: wsjcpp reads directly from the [GitHub repository](https://github.com/nlohmann/json) and is always up-to-date.
## CPM.cmake ## CPM.cmake
If you are using [`CPM.cmake`](https://github.com/TheLartians/CPM.cmake), you can check this [`example`](https://github.com/TheLartians/CPM.cmake/tree/master/examples/json). After [adding CPM script](https://github.com/TheLartians/CPM.cmake#adding-cpm) to your project, implement the following snippet to your CMake: If you are using [`CPM.cmake`](https://github.com/TheLartians/CPM.cmake), you can check this [`example`](https://github.com/TheLartians/CPM.cmake/tree/master/examples/json). After [adding CPM script](https://github.com/TheLartians/CPM.cmake#adding-cpm) to your project, implement the following snippet to your CMake:

View File

@ -464,7 +464,8 @@ void from_json(const BasicJsonType& j, std_fs::path& p)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_string())) if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{ {
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); // Not tested because of #3377 (related #3070)
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); // LCOV_EXCL_LINE
} }
p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
} }

View File

@ -352,7 +352,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
@brief post-increment (it++) @brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl const operator++(int) // NOLINT(readability-const-return-type) iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
++(*this); ++(*this);
@ -403,7 +403,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
@brief post-decrement (it--) @brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl const operator--(int) // NOLINT(readability-const-return-type) iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
--(*this); --(*this);

View File

@ -48,7 +48,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++) /// post-increment (it++)
json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type) json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
{ {
return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
} }
@ -60,7 +60,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
} }
/// post-decrement (it--) /// post-decrement (it--)
json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type) json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
{ {
return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
} }

View File

@ -87,7 +87,7 @@ class primitive_iterator_t
return *this; return *this;
} }
primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type) primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
++m_it; ++m_it;
@ -100,7 +100,7 @@ class primitive_iterator_t
return *this; return *this;
} }
primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type) primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
--m_it; --m_it;

View File

@ -97,6 +97,15 @@
#define JSON_HAS_FILESYSTEM 0 #define JSON_HAS_FILESYSTEM 0
#endif #endif
#ifndef JSON_HAS_THREE_WAY_COMPARISON
#if defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L \
&& defined(__cpp_impl_three_way_comparison)&& __cpp_impl_three_way_comparison >= 201907L
#define JSON_HAS_THREE_WAY_COMPARISON 1
#else
#define JSON_HAS_THREE_WAY_COMPARISON 0
#endif
#endif
// disable documentation warnings on clang // disable documentation warnings on clang
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic push #pragma clang diagnostic push
@ -334,6 +343,7 @@
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
/*! /*!
@brief macro @brief macro
@ -344,6 +354,10 @@
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
/*! /*!
@brief macro @brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@ -353,6 +367,10 @@
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
// inspired from https://stackoverflow.com/a/26745591 // inspired from https://stackoverflow.com/a/26745591
// allows to call any std function as if (e.g. with begin): // allows to call any std function as if (e.g. with begin):

View File

@ -8,19 +8,23 @@
// clean up // clean up
#undef JSON_ASSERT #undef JSON_ASSERT
#undef JSON_INTERNAL_CATCH #undef JSON_INTERNAL_CATCH
#undef JSON_CATCH
#undef JSON_THROW #undef JSON_THROW
#undef JSON_TRY
#undef JSON_PRIVATE_UNLESS_TESTED #undef JSON_PRIVATE_UNLESS_TESTED
#undef JSON_HAS_CPP_11
#undef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_20
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
#undef NLOHMANN_BASIC_JSON_TPL #undef NLOHMANN_BASIC_JSON_TPL
#undef JSON_EXPLICIT #undef JSON_EXPLICIT
#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
#ifndef JSON_TEST_KEEP_MACROS
#undef JSON_CATCH
#undef JSON_TRY
#undef JSON_HAS_CPP_11
#undef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_20
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#undef JSON_HAS_THREE_WAY_COMPARISON
#endif
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp> #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>

View File

@ -147,8 +147,12 @@ struct static_const
static constexpr T value{}; static constexpr T value{};
}; };
template<typename T> #ifndef JSON_HAS_CPP_17
constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
template<typename T>
constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
#endif
} // namespace detail } // namespace detail
} // namespace nlohmann } // namespace nlohmann

View File

@ -1872,6 +1872,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template < typename ValueType, typename std::enable_if < template < typename ValueType, typename std::enable_if <
detail::conjunction < detail::conjunction <
detail::negation<std::is_pointer<ValueType>>, detail::negation<std::is_pointer<ValueType>>,
detail::negation<std::is_same<ValueType, std::nullptr_t>>,
detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>, detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
detail::negation<std::is_same<ValueType, typename string_t::value_type>>, detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
detail::negation<detail::is_basic_json<ValueType>>, detail::negation<detail::is_basic_json<ValueType>>,

View File

@ -30,11 +30,12 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
// Explicit constructors instead of `using Container::Container` // Explicit constructors instead of `using Container::Container`
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} ordered_map() noexcept(noexcept(Container())) : Container{} {}
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
template <class It> template <class It>
ordered_map(It first, It last, const Allocator& alloc = Allocator()) ordered_map(It first, It last, const Allocator& alloc = Allocator())
: Container{first, last, alloc} {} : Container{first, last, alloc} {}
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() ) ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {} : Container{init, alloc} {}
std::pair<iterator, bool> emplace(const key_type& key, T&& t) std::pair<iterator, bool> emplace(const key_type& key, T&& t)

View File

@ -2394,6 +2394,15 @@ using is_detected_convertible =
#define JSON_HAS_FILESYSTEM 0 #define JSON_HAS_FILESYSTEM 0
#endif #endif
#ifndef JSON_HAS_THREE_WAY_COMPARISON
#if defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L \
&& defined(__cpp_impl_three_way_comparison)&& __cpp_impl_three_way_comparison >= 201907L
#define JSON_HAS_THREE_WAY_COMPARISON 1
#else
#define JSON_HAS_THREE_WAY_COMPARISON 0
#endif
#endif
// disable documentation warnings on clang // disable documentation warnings on clang
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic push #pragma clang diagnostic push
@ -2631,6 +2640,7 @@ using is_detected_convertible =
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
/*! /*!
@brief macro @brief macro
@ -2641,6 +2651,10 @@ using is_detected_convertible =
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
/*! /*!
@brief macro @brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@ -2650,6 +2664,10 @@ using is_detected_convertible =
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
// inspired from https://stackoverflow.com/a/26745591 // inspired from https://stackoverflow.com/a/26745591
// allows to call any std function as if (e.g. with begin): // allows to call any std function as if (e.g. with begin):
@ -3173,8 +3191,12 @@ struct static_const
static constexpr T value{}; static constexpr T value{};
}; };
template<typename T> #ifndef JSON_HAS_CPP_17
constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
template<typename T>
constexpr T static_const<T>::value; // NOLINT(readability-redundant-declaration)
#endif
} // namespace detail } // namespace detail
} // namespace nlohmann } // namespace nlohmann
@ -4257,7 +4279,8 @@ void from_json(const BasicJsonType& j, std_fs::path& p)
{ {
if (JSON_HEDLEY_UNLIKELY(!j.is_string())) if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{ {
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); // Not tested because of #3377 (related #3070)
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); // LCOV_EXCL_LINE
} }
p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
} }
@ -11299,7 +11322,7 @@ class primitive_iterator_t
return *this; return *this;
} }
primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type) primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
++m_it; ++m_it;
@ -11312,7 +11335,7 @@ class primitive_iterator_t
return *this; return *this;
} }
primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type) primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
--m_it; --m_it;
@ -11719,7 +11742,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
@brief post-increment (it++) @brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl const operator++(int) // NOLINT(readability-const-return-type) iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
++(*this); ++(*this);
@ -11770,7 +11793,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
@brief post-decrement (it--) @brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl const operator--(int) // NOLINT(readability-const-return-type) iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
{ {
auto result = *this; auto result = *this;
--(*this); --(*this);
@ -12158,7 +12181,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++) /// post-increment (it++)
json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type) json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
{ {
return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
} }
@ -12170,7 +12193,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
} }
/// post-decrement (it--) /// post-decrement (it--)
json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type) json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
{ {
return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
} }
@ -17057,11 +17080,12 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
// Explicit constructors instead of `using Container::Container` // Explicit constructors instead of `using Container::Container`
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} ordered_map() noexcept(noexcept(Container())) : Container{} {}
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
template <class It> template <class It>
ordered_map(It first, It last, const Allocator& alloc = Allocator()) ordered_map(It first, It last, const Allocator& alloc = Allocator())
: Container{first, last, alloc} {} : Container{first, last, alloc} {}
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() ) ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {} : Container{init, alloc} {}
std::pair<iterator, bool> emplace(const key_type& key, T&& t) std::pair<iterator, bool> emplace(const key_type& key, T&& t)
@ -19043,6 +19067,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
template < typename ValueType, typename std::enable_if < template < typename ValueType, typename std::enable_if <
detail::conjunction < detail::conjunction <
detail::negation<std::is_pointer<ValueType>>, detail::negation<std::is_pointer<ValueType>>,
detail::negation<std::is_same<ValueType, std::nullptr_t>>,
detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>, detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
detail::negation<std::is_same<ValueType, typename string_t::value_type>>, detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
detail::negation<detail::is_basic_json<ValueType>>, detail::negation<detail::is_basic_json<ValueType>>,
@ -21928,21 +21953,25 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
// clean up // clean up
#undef JSON_ASSERT #undef JSON_ASSERT
#undef JSON_INTERNAL_CATCH #undef JSON_INTERNAL_CATCH
#undef JSON_CATCH
#undef JSON_THROW #undef JSON_THROW
#undef JSON_TRY
#undef JSON_PRIVATE_UNLESS_TESTED #undef JSON_PRIVATE_UNLESS_TESTED
#undef JSON_HAS_CPP_11
#undef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_20
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
#undef NLOHMANN_BASIC_JSON_TPL #undef NLOHMANN_BASIC_JSON_TPL
#undef JSON_EXPLICIT #undef JSON_EXPLICIT
#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
#ifndef JSON_TEST_KEEP_MACROS
#undef JSON_CATCH
#undef JSON_TRY
#undef JSON_HAS_CPP_11
#undef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_20
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#undef JSON_HAS_THREE_WAY_COMPARISON
#endif
// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>

View File

@ -1,163 +1,131 @@
cmake_minimum_required(VERSION 3.13)
option(JSON_Valgrind "Execute test suite with Valgrind." OFF) option(JSON_Valgrind "Execute test suite with Valgrind." OFF)
option(JSON_FastTests "Skip expensive/slow tests." OFF) option(JSON_FastTests "Skip expensive/slow tests." OFF)
# download test data set(JSON_TestStandards "" CACHE STRING "The list of standards to test explicitly.")
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/download_test_data.cmake)
# test fixture to download test data include(test)
add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target download_test_data)
set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA)
if(JSON_Valgrind) #############################################################################
find_program(CMAKE_MEMORYCHECK_COMMAND valgrind) # override standard support
message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})") #############################################################################
set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full")
separate_arguments(memcheck_command) # compiling json.hpp in C++14 mode fails with Clang <4.0
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0)
unset(compiler_supports_cpp_14)
endif() endif()
#############################################################################
# doctest library with the main function to speed up build
#############################################################################
add_library(doctest_main OBJECT src/unit.cpp)
set_target_properties(doctest_main PROPERTIES
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
)
if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
target_compile_features(doctest_main PUBLIC cxx_range_for)
else()
target_compile_features(doctest_main PUBLIC cxx_std_11)
endif()
target_include_directories(doctest_main PRIVATE "thirdparty/doctest")
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
# Disable warning C4566: character represented by universal-character-name '\uFF01' cannot be represented in the current code page (1252)
# Disable warning C4996: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::operator <<': was declared deprecated
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4566 /wd4996")
# https://github.com/nlohmann/json/issues/1114
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")
endif()
#############################################################################
# one executable for each unit test file
#############################################################################
# check if compiler supports C++17
foreach(feature ${CMAKE_CXX_COMPILE_FEATURES})
if (${feature} STREQUAL cxx_std_17)
set(compiler_supports_cpp_17 TRUE)
endif()
endforeach()
# Clang only supports C++17 starting from Clang 5.0 # Clang only supports C++17 starting from Clang 5.0
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
unset(compiler_supports_cpp_17) unset(compiler_supports_cpp_17)
endif() endif()
# MSVC 2015 (14.0) does not support C++17 # MSVC 2015 (14.0) does not support C++17
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.1) if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.1)
unset(compiler_supports_cpp_17) unset(compiler_supports_cpp_17)
endif() endif()
file(GLOB files src/unit-*.cpp) # Clang C++20 support appears insufficient prior to Clang 9.0 (based on CI build failure)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
unset(compiler_supports_cpp_20)
endif()
# GCC started supporting C++20 features in 8.0 but a test for #3070 segfaults prior to 9.0
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
unset(compiler_supports_cpp_20)
endif()
foreach(file ${files}) #############################################################################
get_filename_component(file_basename ${file} NAME_WE) # test_main library with shared code to speed up build and common settings
string(REGEX REPLACE "unit-([^$]+)" "test-\\1" testcase ${file_basename}) #############################################################################
add_executable(${testcase} $<TARGET_OBJECTS:doctest_main> ${file}) add_library(test_main OBJECT src/unit.cpp)
target_compile_definitions(${testcase} PRIVATE DOCTEST_CONFIG_SUPER_FAST_ASSERTS) target_compile_definitions(test_main PUBLIC
target_compile_options(${testcase} PRIVATE DOCTEST_CONFIG_SUPER_FAST_ASSERTS
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>> JSON_TEST_KEEP_MACROS
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated;-Wno-float-equal> )
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations> target_compile_features(test_main PRIVATE cxx_std_11)
) target_compile_options(test_main PUBLIC
target_include_directories(${testcase} PRIVATE ${CMAKE_BINARY_DIR}/include thirdparty/doctest thirdparty/fifo_map) $<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>
target_link_libraries(${testcase} PRIVATE ${NLOHMANN_JSON_TARGET_NAME}) # MSVC: Force to always compile with W4
# Disable warning C4566: character represented by universal-character-name '\uFF01'
# cannot be represented in the current code page (1252)
# Disable warning C4996: 'nlohmann::basic_json<...>::operator <<': was declared deprecated
$<$<CXX_COMPILER_ID:MSVC>:/W4 /wd4566 /wd4996>
# https://github.com/nlohmann/json/issues/1114
$<$<CXX_COMPILER_ID:MSVC>:/bigobj> $<$<BOOL:${MINGW}>:-Wa,-mbig-obj>
# add a copy with C++17 compilation $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated;-Wno-float-equal>
if (compiler_supports_cpp_17) $<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
file(READ ${file} FILE_CONTENT) )
string(FIND "${FILE_CONTENT}" "JSON_HAS_CPP_17" CPP_17_FOUND) target_include_directories(test_main PUBLIC
if(NOT ${CPP_17_FOUND} EQUAL -1) thirdparty/doctest
add_executable(${testcase}_cpp17 $<TARGET_OBJECTS:doctest_main> ${file}) thirdparty/fifo_map
target_compile_definitions(${testcase}_cpp17 PRIVATE DOCTEST_CONFIG_SUPER_FAST_ASSERTS) ${PROJECT_BINARY_DIR}/include
target_compile_options(${testcase}_cpp17 PRIVATE )
$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>> target_link_libraries(test_main PUBLIC ${NLOHMANN_JSON_TARGET_NAME})
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated;-Wno-float-equal>
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
)
target_include_directories(${testcase}_cpp17 PRIVATE ${CMAKE_BINARY_DIR}/include thirdparty/doctest thirdparty/fifo_map)
target_link_libraries(${testcase}_cpp17 PRIVATE ${NLOHMANN_JSON_TARGET_NAME})
target_compile_features(${testcase}_cpp17 PRIVATE cxx_std_17)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0 AND NOT MINGW) #############################################################################
# fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90050 # define test- and standard-specific build settings
target_link_libraries(${testcase}_cpp17 PRIVATE stdc++fs) #############################################################################
endif()
if (JSON_FastTests) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
add_test(NAME "${testcase}_cpp17" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0
COMMAND ${testcase}_cpp17 ${DOCTEST_TEST_FILTER} AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0 AND NOT MINGW)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} # fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90050
) json_test_set_test_options(all CXX_STANDARDS 17 LINK_LIBRARIES stdc++fs)
else() endif()
add_test(NAME "${testcase}_cpp17"
COMMAND ${testcase}_cpp17 ${DOCTEST_TEST_FILTER} --no-skip
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
set_tests_properties("${testcase}_cpp17" PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
endif()
endif()
if (JSON_FastTests) if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_test(NAME "${testcase}" # avoid stack overflow, see https://github.com/nlohmann/json/issues/2955
COMMAND ${testcase} ${DOCTEST_TEST_FILTER} json_test_set_test_options("test-cbor;test-msgpack;test-ubjson" LINK_OPTIONS /STACK:4000000)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} endif()
)
else()
add_test(NAME "${testcase}"
COMMAND ${testcase} ${DOCTEST_TEST_FILTER} --no-skip
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
set_tests_properties("${testcase}" PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
if(JSON_Valgrind)
add_test(NAME "${testcase}_valgrind"
COMMAND ${memcheck_command} ${CMAKE_CURRENT_BINARY_DIR}/${testcase} ${DOCTEST_TEST_FILTER}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
set_tests_properties("${testcase}_valgrind" PROPERTIES LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA)
endif()
endforeach()
# disable exceptions for test-disabled_exceptions # disable exceptions for test-disabled_exceptions
target_compile_definitions(test-disabled_exceptions PUBLIC JSON_NOEXCEPTION) json_test_set_test_options(test-disabled_exceptions COMPILE_DEFINITIONS JSON_NOEXCEPTION)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(test-disabled_exceptions PUBLIC -fno-exceptions) json_test_set_test_options(test-disabled_exceptions COMPILE_OPTIONS -fno-exceptions)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# disabled due to https://github.com/nlohmann/json/discussions/2824 # disabled due to https://github.com/nlohmann/json/discussions/2824
#target_compile_options(test-disabled_exceptions PUBLIC /EH) #json_test_set_test_options(test-disabled_exceptions COMPILE_DEFINITIONS _HAS_EXCEPTIONS=0 COMPILE_OPTIONS /EH)
#target_compile_definitions(test-disabled_exceptions PUBLIC _HAS_EXCEPTIONS=0)
endif() endif()
# avoid stack overflow, see https://github.com/nlohmann/json/issues/2955 #############################################################################
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # add unit tests
set_property(TARGET test-cbor APPEND_STRING PROPERTY LINK_FLAGS " /STACK:4000000") #############################################################################
set_property(TARGET test-msgpack APPEND_STRING PROPERTY LINK_FLAGS " /STACK:4000000")
set_property(TARGET test-ubjson APPEND_STRING PROPERTY LINK_FLAGS " /STACK:4000000") if("${JSON_TestStandards}" STREQUAL "")
set(test_cxx_standards 11 14 17 20 23)
unset(test_force)
else()
set(test_cxx_standards ${JSON_TestStandards})
set(test_force FORCE)
endif() endif()
# Print selected standards marking unavailable ones with brackets
set(msg_standards "")
foreach(cxx_standard ${test_cxx_standards})
if(compiler_supports_cpp_${cxx_standard})
list(APPEND msg_standards ${cxx_standard})
else()
list(APPEND msg_standards [${cxx_standard}])
endif()
endforeach()
string(JOIN " " msg_standards ${msg_standards})
set(msg "Testing standards: ${msg_standards}")
if(test_force)
string(APPEND msg " (forced)")
endif()
message(STATUS "${msg}")
# *DO* use json_test_set_test_options() above this line
file(GLOB files src/unit-*.cpp)
foreach(file ${files})
json_test_add_test_for(${file} MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force})
endforeach()
# *DO NOT* use json_test_set_test_options() below this line
############################################################################# #############################################################################
# Test the generated build configs # Test the generated build configs
############################################################################# #############################################################################
@ -170,4 +138,5 @@ endif()
add_subdirectory(cmake_add_subdirectory) add_subdirectory(cmake_add_subdirectory)
add_subdirectory(cmake_fetch_content) add_subdirectory(cmake_fetch_content)
add_subdirectory(cmake_fetch_content2)
add_subdirectory(cmake_target_include_directories) add_subdirectory(cmake_target_include_directories)

View File

@ -0,0 +1,20 @@
if (${CMAKE_VERSION} VERSION_GREATER "3.14.0")
add_test(NAME cmake_fetch_content2_configure
COMMAND ${CMAKE_COMMAND}
-G "${CMAKE_GENERATOR}"
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-Dnlohmann_json_source=${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/project
)
add_test(NAME cmake_fetch_content2_build
COMMAND ${CMAKE_COMMAND} --build .
)
set_tests_properties(cmake_fetch_content2_configure PROPERTIES
FIXTURES_SETUP cmake_fetch_content2
LABELS "git_required;not_reproducible"
)
set_tests_properties(cmake_fetch_content2_build PROPERTIES
FIXTURES_REQUIRED cmake_fetch_content2
LABELS "git_required;not_reproducible"
)
endif()

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.14)
project(DummyImport CXX)
include(FetchContent)
get_filename_component(GIT_REPOSITORY_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../.. ABSOLUTE)
FetchContent_Declare(json GIT_REPOSITORY ${GIT_REPOSITORY_DIRECTORY} GIT_TAG HEAD)
FetchContent_MakeAvailable(json)
add_executable(with_namespace_target main.cpp)
target_link_libraries(with_namespace_target nlohmann_json::nlohmann_json)
add_executable(without_namespace_target main.cpp)
target_link_libraries(without_namespace_target nlohmann_json)

View File

@ -0,0 +1,8 @@
#include <nlohmann/json.hpp>
int main(int argc, char **argv)
{
nlohmann::json j;
return 0;
}

View File

@ -39,6 +39,8 @@ namespace
template<class T> template<class T>
struct bad_allocator : std::allocator<T> struct bad_allocator : std::allocator<T>
{ {
using std::allocator<T>::allocator;
template<class... Args> template<class... Args>
void construct(T* /*unused*/, Args&& ... /*unused*/) void construct(T* /*unused*/, Args&& ... /*unused*/)
{ {

View File

@ -37,7 +37,7 @@ SOFTWARE.
/* forward declarations */ /* forward declarations */
class alt_string; class alt_string;
bool operator<(const char* op1, const alt_string& op2); bool operator<(const char* op1, const alt_string& op2) noexcept;
void int_to_string(alt_string& target, std::size_t value); void int_to_string(alt_string& target, std::size_t value);
/* /*
@ -104,12 +104,12 @@ class alt_string
} }
template <typename op_type> template <typename op_type>
bool operator<(const op_type& op) const bool operator<(const op_type& op) const noexcept
{ {
return str_impl < op; return str_impl < op;
} }
bool operator<(const alt_string& op) const bool operator<(const alt_string& op) const noexcept
{ {
return str_impl < op.str_impl; return str_impl < op.str_impl;
} }
@ -152,7 +152,7 @@ class alt_string
private: private:
std::string str_impl {}; std::string str_impl {};
friend bool ::operator<(const char* /*op1*/, const alt_string& /*op2*/); friend bool ::operator<(const char* /*op1*/, const alt_string& /*op2*/) noexcept;
}; };
void int_to_string(alt_string& target, std::size_t value) void int_to_string(alt_string& target, std::size_t value)
@ -172,7 +172,7 @@ using alt_json = nlohmann::basic_json <
nlohmann::adl_serializer >; nlohmann::adl_serializer >;
bool operator<(const char* op1, const alt_string& op2) bool operator<(const char* op1, const alt_string& op2) noexcept
{ {
return op1 < op2.str_impl; return op1 < op2.str_impl;
} }

View File

@ -1609,7 +1609,7 @@ TEST_CASE("CBOR")
// callback to set binary_seen to true if a binary value was seen // callback to set binary_seen to true if a binary value was seen
bool binary_seen = false; bool binary_seen = false;
auto callback = [&binary_seen](int /*depth*/, json::parse_event_t /*event*/, json & parsed) auto callback = [&binary_seen](int /*depth*/, json::parse_event_t /*event*/, json & parsed) noexcept
{ {
if (parsed.is_binary()) if (parsed.is_binary())
{ {

View File

@ -33,6 +33,12 @@ SOFTWARE.
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
template<typename Iter>
using can_post_increment_temporary = decltype((std::declval<Iter>()++)++);
template<typename Iter>
using can_post_decrement_temporary = decltype((std::declval<Iter>()--)--);
TEST_CASE("iterator class") TEST_CASE("iterator class")
{ {
SECTION("construction") SECTION("construction")
@ -399,4 +405,89 @@ TEST_CASE("iterator class")
} }
} }
} }
SECTION("equality-preserving")
{
SECTION("post-increment")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
}
SECTION("post-decrement")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
}
}
}
// prevent "accidental mutation of a temporary object"
SECTION("cert-dcl21-cpp")
{
using nlohmann::detail::is_detected;
SECTION("post-increment")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK_FALSE(is_detected<can_post_increment_temporary, Iter&>::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK_FALSE(is_detected<can_post_increment_temporary, Iter&>::value);
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK_FALSE(is_detected<can_post_increment_temporary, Iter&>::value);
}
}
SECTION("post-decrement")
{
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
}
}
}
} }

View File

@ -267,7 +267,7 @@ bool accept_helper(const std::string& s)
CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == !el.errored); CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == !el.errored);
// 5. parse with simple callback // 5. parse with simple callback
json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept
{ {
return true; return true;
}; };
@ -1499,7 +1499,7 @@ TEST_CASE("parser class")
// test case to make sure the callback is properly evaluated after reading a key // test case to make sure the callback is properly evaluated after reading a key
{ {
json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t event, json& /*unused*/) json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t event, json& /*unused*/) noexcept
{ {
return event != json::parse_event_t::key; return event != json::parse_event_t::key;
}; };
@ -1538,14 +1538,14 @@ TEST_CASE("parser class")
SECTION("filter nothing") SECTION("filter nothing")
{ {
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
{ {
return true; return true;
}); });
CHECK (j_object == json({{"foo", 2}, {"bar", {{"baz", 1}}}})); CHECK (j_object == json({{"foo", 2}, {"bar", {{"baz", 1}}}}));
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
{ {
return true; return true;
}); });
@ -1555,7 +1555,7 @@ TEST_CASE("parser class")
SECTION("filter everything") SECTION("filter everything")
{ {
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
{ {
return false; return false;
}); });
@ -1563,7 +1563,7 @@ TEST_CASE("parser class")
// the top-level object will be discarded, leaving a null // the top-level object will be discarded, leaving a null
CHECK (j_object.is_null()); CHECK (j_object.is_null());
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
{ {
return false; return false;
}); });
@ -1574,7 +1574,7 @@ TEST_CASE("parser class")
SECTION("filter specific element") SECTION("filter specific element")
{ {
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
{ {
// filter all number(2) elements // filter all number(2) elements
return j != json(2); return j != json(2);
@ -1582,7 +1582,7 @@ TEST_CASE("parser class")
CHECK (j_object == json({{"bar", {{"baz", 1}}}})); CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
{ {
return j != json(2); return j != json(2);
}); });
@ -1601,7 +1601,7 @@ TEST_CASE("parser class")
CHECK (j_filtered1.size() == 2); CHECK (j_filtered1.size() == 2);
CHECK (j_filtered1 == json({1, {{"qux", "baz"}}})); CHECK (j_filtered1 == json({1, {{"qux", "baz"}}}));
json j_filtered2 = json::parse(structured_array, [](int /*unused*/, json::parse_event_t e, const json& /*parsed*/) json j_filtered2 = json::parse(structured_array, [](int /*unused*/, json::parse_event_t e, const json& /*parsed*/) noexcept
{ {
return e != json::parse_event_t::object_end; return e != json::parse_event_t::object_end;
}); });
@ -1616,7 +1616,7 @@ TEST_CASE("parser class")
SECTION("first closing event") SECTION("first closing event")
{ {
{ {
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
{ {
static bool first = true; static bool first = true;
if (e == json::parse_event_t::object_end && first) if (e == json::parse_event_t::object_end && first)
@ -1633,7 +1633,7 @@ TEST_CASE("parser class")
} }
{ {
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
{ {
static bool first = true; static bool first = true;
if (e == json::parse_event_t::array_end && first) if (e == json::parse_event_t::array_end && first)
@ -1657,13 +1657,13 @@ TEST_CASE("parser class")
// object and array is discarded only after the closing character // object and array is discarded only after the closing character
// has been read // has been read
json j_empty_object = json::parse("{}", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) json j_empty_object = json::parse("{}", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
{ {
return e != json::parse_event_t::object_end; return e != json::parse_event_t::object_end;
}); });
CHECK(j_empty_object == json()); CHECK(j_empty_object == json());
json j_empty_array = json::parse("[]", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) json j_empty_array = json::parse("[]", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
{ {
return e != json::parse_event_t::array_end; return e != json::parse_event_t::array_end;
}); });
@ -1731,7 +1731,7 @@ TEST_CASE("parser class")
{ {
SECTION("parser with callback") SECTION("parser with callback")
{ {
json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept
{ {
return true; return true;
}; };

View File

@ -205,6 +205,14 @@ TEST_CASE("lexicographical comparison operators")
{ {
for (size_t j = 0; j < j_values.size(); ++j) for (size_t j = 0; j < j_values.size(); ++j)
{ {
// Skip comparing indicies 12 and 13, and 13 and 12 in C++20 pending fix
// See issue #3207
#if defined(JSON_HAS_CPP_20) || JSON_HAS_THREE_WAY_COMPARISON
if ((i == 12 && j == 13) || (i == 13 && j == 12))
{
continue;
}
#endif
CAPTURE(i) CAPTURE(i)
CAPTURE(j) CAPTURE(j)
CAPTURE(j_values[i]) CAPTURE(j_values[i])

View File

@ -41,13 +41,6 @@ using nlohmann::json;
#include <unordered_set> #include <unordered_set>
#include <valarray> #include <valarray>
#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
// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair // NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")

View File

@ -32,13 +32,6 @@ SOFTWARE.
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
using nlohmann::json; using nlohmann::json;
#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
// This test suite uses range for loops where values are copied. This is inefficient in usual code, but required to achieve 100% coverage. // This test suite uses range for loops where values are copied. This is inefficient in usual code, but required to achieve 100% coverage.
DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING_PUSH
DOCTEST_GCC_SUPPRESS_WARNING("-Wrange-loop-construct") DOCTEST_GCC_SUPPRESS_WARNING("-Wrange-loop-construct")

View File

@ -42,10 +42,6 @@ using nlohmann::json;
#include <cstdio> #include <cstdio>
#include <test_data.hpp> #include <test_data.hpp>
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
#define JSON_HAS_CPP_17
#endif
#ifdef JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17
#include <variant> #include <variant>
#endif #endif

View File

@ -42,70 +42,8 @@ using ordered_json = nlohmann::ordered_json;
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
#define JSON_HAS_CPP_17
#endif
#ifdef JSON_HAS_CPP_17 #ifdef JSON_HAS_CPP_17
#include <variant> #include <variant>
#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
#if defined(__cpp_lib_filesystem)
#define JSON_HAS_FILESYSTEM 1
#elif defined(__cpp_lib_experimental_filesystem)
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
#elif !defined(__has_include)
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
#elif __has_include(<filesystem>)
#define JSON_HAS_FILESYSTEM 1
#elif __has_include(<experimental/filesystem>)
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
#endif
// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#endif
// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
#if defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#endif
// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
#if defined(__clang_major__) && __clang_major__ < 7
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#endif
// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
#if defined(_MSC_VER) && _MSC_VER < 1940
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#endif
// no filesystem support before iOS 13
#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#endif
// no filesystem support before macOS Catalina
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
#undef JSON_HAS_FILESYSTEM
#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#endif
#endif
#endif
#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
#endif
#ifndef JSON_HAS_FILESYSTEM
#define JSON_HAS_FILESYSTEM 0
#endif #endif
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
@ -271,7 +209,10 @@ std::string* sax_no_exception::error_string = nullptr;
template<class T> template<class T>
class my_allocator : public std::allocator<T> class my_allocator : public std::allocator<T>
{}; {
public:
using std::allocator<T>::allocator;
};
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// for #3077 // for #3077
@ -338,7 +279,7 @@ TEST_CASE("regression tests 2")
] ]
})"; })";
json::parser_callback_t cb = [&](int /*level*/, json::parse_event_t event, json & parsed) json::parser_callback_t cb = [&](int /*level*/, json::parse_event_t event, json & parsed) noexcept
{ {
// skip uninteresting events // skip uninteresting events
if (event == json::parse_event_t::value && !parsed.is_primitive()) if (event == json::parse_event_t::value && !parsed.is_primitive())
@ -653,7 +594,7 @@ TEST_CASE("regression tests 2")
#ifdef JSON_HAS_CPP_20 #ifdef JSON_HAS_CPP_20
SECTION("issue #2546 - parsing containers of std::byte") SECTION("issue #2546 - parsing containers of std::byte")
{ {
const char DATA[] = R"("Hello, world!")"; const char DATA[] = R"("Hello, world!")"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
const auto s = std::as_bytes(std::span(DATA)); const auto s = std::as_bytes(std::span(DATA));
json j = json::parse(s); json j = json::parse(s);
CHECK(j.dump() == "\"Hello, world!\""); CHECK(j.dump() == "\"Hello, world!\"");
@ -807,7 +748,8 @@ TEST_CASE("regression tests 2")
const auto j_path = j.get<nlohmann::detail::std_fs::path>(); const auto j_path = j.get<nlohmann::detail::std_fs::path>();
CHECK(j_path == text_path); CHECK(j_path == text_path);
CHECK_THROWS_WITH_AS(nlohmann::detail::std_fs::path(json(1)), "[json.exception.type_error.302] type must be string, but is number", json::type_error); // Disabled pending resolution of #3377
// CHECK_THROWS_WITH_AS(nlohmann::detail::std_fs::path(json(1)), "[json.exception.type_error.302] type must be string, but is number", json::type_error);
} }
#endif #endif
@ -835,6 +777,18 @@ TEST_CASE("regression tests 2")
CHECK(j.dump() == "[1,4]"); CHECK(j.dump() == "[1,4]");
} }
SECTION("issue #3343 - json and ordered_json are not interchangable")
{
json::object_t jobj({ { "product", "one" } });
ordered_json::object_t ojobj({{"product", "one"}});
auto jit = jobj.begin();
auto ojit = ojobj.begin();
CHECK(jit->first == ojit->first);
CHECK(jit->second.get<std::string>() == ojit->second.get<std::string>());
}
} }
DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_CLANG_SUPPRESS_WARNING_POP

View File

@ -1610,7 +1610,7 @@ TEST_CASE("UBJSON")
CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&); CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
json j; json j;
nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
{ {
return true; return true;
}); });
@ -1624,7 +1624,7 @@ TEST_CASE("UBJSON")
CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&); CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&);
json j; json j;
nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
{ {
return true; return true;
}); });

View File

@ -59,6 +59,42 @@ class person_with_private_data
NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name, metadata) NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name, metadata)
}; };
class person_with_private_data_2
{
private:
std::string name{};
int age = 0;
json metadata = nullptr;
public:
bool operator==(const person_with_private_data_2& rhs) const
{
return name == rhs.name && age == rhs.age && metadata == rhs.metadata;
}
person_with_private_data_2() = default;
person_with_private_data_2(std::string name_, int age_, json metadata_)
: name(std::move(name_))
, age(age_)
, metadata(std::move(metadata_))
{}
std::string getName() const
{
return name;
}
int getAge() const
{
return age;
}
json getMetadata() const
{
return metadata;
}
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(person_with_private_data_2, age, name, metadata)
};
class person_without_private_data_1 class person_without_private_data_1
{ {
public: public:
@ -103,6 +139,41 @@ class person_without_private_data_2
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, metadata) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, metadata)
class person_without_private_data_3
{
public:
std::string name{};
int age = 0;
json metadata = nullptr;
bool operator==(const person_without_private_data_3& rhs) const
{
return name == rhs.name && age == rhs.age && metadata == rhs.metadata;
}
person_without_private_data_3() = default;
person_without_private_data_3(std::string name_, int age_, json metadata_)
: name(std::move(name_))
, age(age_)
, metadata(std::move(metadata_))
{}
std::string getName() const
{
return name;
}
int getAge() const
{
return age;
}
json getMetadata() const
{
return metadata;
}
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(person_without_private_data_3, age, name, metadata)
class person_with_private_alphabet class person_with_private_alphabet
{ {
public: public:
@ -231,7 +302,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_with_public_alphabet, a, b, c, d, e, f
} // namespace persons } // namespace persons
TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE", T, TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T,
persons::person_with_private_data, persons::person_with_private_data,
persons::person_without_private_data_1, persons::person_without_private_data_1,
persons::person_without_private_data_2) persons::person_without_private_data_2)
@ -257,6 +328,40 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRU
} }
} }
TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT", T,
persons::person_with_private_data_2,
persons::person_without_private_data_3)
{
SECTION("person with default values")
{
// serialization of default constructed object
T p0;
CHECK(json(p0).dump() == "{\"age\":0,\"metadata\":null,\"name\":\"\"}");
// serialization
T p1("Erik", 1, {{"haircuts", 2}});
CHECK(json(p1).dump() == "{\"age\":1,\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}");
// deserialization
auto p2 = json(p1).get<T>();
CHECK(p2 == p1);
// roundtrip
CHECK(T(json(p1)) == p1);
CHECK(json(T(json(p1))) == json(p1));
// check default value in case of missing field
json j = json(p1);
j.erase("name");
j.erase("age");
j.erase("metadata");
T p3 = j.get<T>();
CHECK(p3.getName() == "");
CHECK(p3.getAge() == 0);
CHECK(p3.getMetadata() == nullptr);
}
}
TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T, TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T,
persons::person_with_private_alphabet, persons::person_with_private_alphabet,
persons::person_with_public_alphabet) persons::person_with_public_alphabet)