diff --git a/.clang-tidy b/.clang-tidy index 3673930d4..b981348f3 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -43,6 +43,7 @@ Checks: '*, -readability-identifier-length, -readability-magic-numbers, -readability-redundant-access-specifiers, + -readability-simplify-boolean-expr -readability-uppercase-literal-suffix' CheckOptions: diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to .github/CODE_OF_CONDUCT.md diff --git a/.drone.yml b/.github/external_ci/.drone.yml similarity index 97% rename from .drone.yml rename to .github/external_ci/.drone.yml index 3cdefe4b9..0d9e3d0be 100644 --- a/.drone.yml +++ b/.github/external_ci/.drone.yml @@ -18,5 +18,5 @@ steps: - cd build - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON - make -j10 - - cd test + - cd tests - ../../cmake-3.20.2/bin/ctest -j10 diff --git a/appveyor.yml b/.github/external_ci/appveyor.yml similarity index 100% rename from appveyor.yml rename to .github/external_ci/appveyor.yml diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 03c652a81..28e0b74fd 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -10,7 +10,7 @@ on: workflow_dispatch: jobs: - xcode: + xcode_1: runs-on: macos-10.15 strategy: matrix: @@ -27,8 +27,25 @@ jobs: - name: test run: cd build ; ctest -j 10 --output-on-failure + xcode_2: + runs-on: macos-12 + strategy: + matrix: + xcode: [13.3.1, 13.3, 13.2.1, 13.2, 13.1] + env: + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer + + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON + - name: build + run: cmake --build build --parallel 10 + - name: test + run: cd build ; ctest -j 10 --output-on-failure + xcode_standards: - runs-on: macos-10.15 + runs-on: macos-latest strategy: matrix: standard: [11, 14, 17, 20] diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index b5f583367..440710427 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -12,7 +12,7 @@ on: jobs: ci_test_clang: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - uses: actions/checkout@v3 - name: cmake @@ -22,7 +22,7 @@ jobs: ci_test_gcc: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - uses: actions/checkout@v3 - name: cmake @@ -32,7 +32,7 @@ jobs: ci_static_analysis: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: target: [ci_clang_tidy, ci_cppcheck, ci_test_valgrind, ci_test_clang_sanitizer, ci_test_amalgamation, ci_clang_analyze, ci_cpplint, ci_cmake_flags, ci_single_binaries, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_infer] @@ -43,12 +43,22 @@ jobs: - name: build run: cmake --build build --target ${{ matrix.target }} + ci_test_single_header: + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -DJSON_CI=On + - name: build + run: cmake --build build --target ci_test_single_header + ci_cmake_options: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: - target: [ci_test_diagnostics, ci_test_noexceptions, ci_test_noimplicitconversions] + target: [ci_test_diagnostics, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison] steps: - uses: actions/checkout@v3 - name: cmake @@ -58,7 +68,7 @@ jobs: ci_test_coverage: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - uses: actions/checkout@v3 - name: cmake @@ -78,10 +88,10 @@ jobs: ci_test_compilers: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: - compiler: [g++-4.8, g++-4.9, g++-5, g++-6, g++-7, g++-8, g++-9, g++-10, clang++-3.5, clang++-3.6, clang++-3.7, clang++-3.8, clang++-3.9, clang++-4.0, clang++-5.0, clang++-6.0, clang++-7, clang++-8, clang++-9, clang++-10, clang++-11, clang++-12, clang++-13, clang++-14] + compiler: [g++-4.8, g++-4.9, g++-5, g++-6, g++-7, g++-8, g++-9, g++-10, g++-11, clang++-3.5, clang++-3.6, clang++-3.7, clang++-3.8, clang++-3.9, clang++-4.0, clang++-5.0, clang++-6.0, clang++-7, clang++-8, clang++-9, clang++-10, clang++-11, clang++-12, clang++-13, clang++-14] steps: - uses: actions/checkout@v3 - name: cmake @@ -91,7 +101,7 @@ jobs: ci_test_standards: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: standard: [11, 14, 17, 20] @@ -105,10 +115,22 @@ jobs: ci_cuda_example: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.3.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build run: cmake --build build --target ci_cuda_example + + ci_icpc: + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.2.0 + steps: + - uses: actions/checkout@v2 + - name: cmake + run: cmake -S . -B build -DJSON_CI=On + - name: build + run: | + . /opt/intel/oneapi/setvars.sh + cmake --build build --target ci_icpc diff --git a/.gitignore b/.gitignore index a13ad89a5..72eb2c225 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,37 @@ -json_unit -json_benchmarks -json_benchmarks_simple -fuzz-testing - *.dSYM *.o *.gcno *.gcda - -build -build_coverage -clang_analyze_build - -benchmarks/files/numbers/*.json +.DS_Store .wsjcpp-logs/* .wsjcpp/* -.idea +/.idea /cmake-build-* -test/test-* -/.vs +/.vs/ +/.vscode/ -doc/html -doc/mkdocs/venv/ -doc/mkdocs/docs/examples -doc/mkdocs/site -doc/mkdocs/docs/__pycache__/ -/doc/docset/JSON_for_Modern_C++.docset/ -/doc/docset/JSON_for_Modern_C++.tgz +# clangd cache +/.cache/ + +# build directories (vscode-cmake-tools, user-defined, ...) +/build*/ + +# fuzzers +/tests/parse_*_fuzzer +/tests/corpus_* + +/docs/mkdocs/docs/examples/ +/docs/mkdocs/docs/__pycache__/ +/docs/mkdocs/site/ +/docs/mkdocs/venv/ +/docs/docset/JSON_for_Modern_C++.docset/ +/docs/docset/JSON_for_Modern_C++.tgz +/docs/mkdocs/docs/images/json.gif + +# serve_header +/serve_header.yml +/localhost.pem +/localhost-key.pem diff --git a/CMakeLists.txt b/CMakeLists.txt index 68bba9cf4..f20d56137 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,13 +37,15 @@ if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} 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_Diagnostics "Use extended diagnostic messages." OFF) -option(JSON_ImplicitConversions "Enable implicit conversions." ON) -option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT}) -option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF) -option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) +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_Diagnostics "Use extended diagnostic messages." OFF) +option(JSON_ImplicitConversions "Enable implicit conversions." ON) +option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF) +option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF) +option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT}) +option(JSON_MultipleHeaders "Use non-amalgamated version of the library." ON) +option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) if (JSON_CI) include(ci) @@ -77,6 +79,14 @@ if (NOT JSON_ImplicitConversions) message(STATUS "Implicit conversions are disabled") endif() +if (JSON_DisableEnumSerialization) + message(STATUS "Enum integer serialization is disabled") +endif() + +if (JSON_LegacyDiscardedValueComparison) + message(STATUS "Legacy discarded value comparison enabled") +endif() + if (JSON_Diagnostics) message(STATUS "Diagnostics enabled") endif() @@ -100,8 +110,10 @@ endif() target_compile_definitions( ${NLOHMANN_JSON_TARGET_NAME} INTERFACE - JSON_USE_IMPLICIT_CONVERSIONS=$ - JSON_DIAGNOSTICS=$ + $<$>:JSON_USE_IMPLICIT_CONVERSIONS=0> + $<$:JSON_DISABLE_ENUM_SERIALIZATION=1> + $<$:JSON_DIAGNOSTICS=1> + $<$:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1> ) target_include_directories( @@ -136,7 +148,7 @@ CONFIGURE_FILE( if (JSON_BuildTests) include(CTest) enable_testing() - add_subdirectory(test) + add_subdirectory(tests) endif() ## diff --git a/Makefile b/Makefile index 597c609cb..ce26524ad 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ all: # compile example files and check output doctest: - $(MAKE) check_output -C doc + $(MAKE) check_output -C docs ########################################################################## @@ -55,7 +55,7 @@ doctest: run_benchmarks: rm -fr cmake-build-benchmarks mkdir cmake-build-benchmarks - cd cmake-build-benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On + cd cmake-build-benchmarks ; cmake ../tests/benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release cd cmake-build-benchmarks ; ninja cd cmake-build-benchmarks ; ./json_benchmarks @@ -68,41 +68,41 @@ run_benchmarks: fuzz_testing: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_afl_fuzzer -C test CXX=afl-clang++ - mv test/parse_afl_fuzzer fuzz-testing/fuzzer - find test/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_afl_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_afl_fuzzer fuzz-testing/fuzzer + find tests/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_bson: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_bson_fuzzer -C test CXX=afl-clang++ - mv test/parse_bson_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.bson | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_bson_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_bson_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.bson | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_cbor: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_cbor_fuzzer -C test CXX=afl-clang++ - mv test/parse_cbor_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_cbor_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_cbor_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_msgpack: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_msgpack_fuzzer -C test CXX=afl-clang++ - mv test/parse_msgpack_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_msgpack_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_msgpack_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_ubjson: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_ubjson_fuzzer -C test CXX=afl-clang++ - mv test/parse_ubjson_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.ubjson | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_ubjson_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_ubjson_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.ubjson | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzzing-start: @@ -159,18 +159,18 @@ pretty: --preserve-date \ --suffix=none \ --formatted \ - $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/src/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp + $(SRCS) $(AMALGAMATED_FILE) tests/src/*.cpp tests/src/*.hpp tests/benchmarks/src/benchmarks.cpp docs/examples/*.cpp # call the Clang-Format on all source files pretty_format: - for FILE in $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/src/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done + for FILE in $(SRCS) $(AMALGAMATED_FILE) tests/src/*.cpp tests/src/*.hpp benchmarks/src/benchmarks.cpp docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done # create single header file amalgamate: $(AMALGAMATED_FILE) # call the amalgamation tool and pretty print $(AMALGAMATED_FILE): $(SRCS) - third_party/amalgamate/amalgamate.py -c third_party/amalgamate/config.json -s . --verbose=yes + tools/amalgamate/amalgamate.py -c tools/amalgamate/config.json -s . --verbose=yes $(MAKE) pretty # check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources @@ -233,10 +233,10 @@ release: include.zip json.tar.xz # clean up clean: - rm -fr fuzz fuzz-testing *.dSYM test/*.dSYM + rm -fr fuzz fuzz-testing *.dSYM tests/*.dSYM rm -fr benchmarks/files/numbers/*.json rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files - $(MAKE) clean -Cdoc + $(MAKE) clean -Cdocs ########################################################################## @@ -251,3 +251,10 @@ update_hedley: $(SED) -i '1s/^/#pragma once\n\n/' include/nlohmann/thirdparty/hedley/hedley.hpp $(SED) -i '1s/^/#pragma once\n\n/' include/nlohmann/thirdparty/hedley/hedley_undef.hpp $(MAKE) amalgamate + +########################################################################## +# serve_header.py +########################################################################## + +serve_header: + ./tools/serve_header/serve_header.py --make $(MAKE) diff --git a/README.md b/README.md index 9d9bd2c91..220b3a9f1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)](https://github.com/nlohmann/json/releases) +[![JSON for Modern C++](docs/json.gif)](https://github.com/nlohmann/json/releases) [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) [![Ubuntu](https://github.com/nlohmann/json/workflows/Ubuntu/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AUbuntu) @@ -32,7 +32,7 @@ - [Implicit conversions](#implicit-conversions) - [Conversions to/from arbitrary types](#arbitrary-types-conversions) - [Specializing enum conversion](#specializing-enum-conversion) - - [Binary formats (BSON, CBOR, MessagePack, and UBJSON)](#binary-formats-bson-cbor-messagepack-and-ubjson) + - [Binary formats (BSON, CBOR, MessagePack, UBJSON, and BJData)](#binary-formats-bson-cbor-messagepack-ubjson-and-bjdata) - [Supported compilers](#supported-compilers) - [Integration](#integration) - [CMake](#cmake) @@ -54,7 +54,7 @@ There are myriads of [JSON](https://json.org) libraries out there, and each may - **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings. -- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/test/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](https://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). +- **Serious testing**. Our code is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/tests/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](https://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). Other aspects were not so important to us: @@ -69,6 +69,10 @@ See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/. You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). +### :office: Corporate Sponsor + +[![](https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Codacy-logo-black.svg/320px-Codacy-logo-black.svg.png)](https://github.com/codacy) + ### :label: Named Sponsors - [Michael Hartmann](https://github.com/reFX-Mike) @@ -83,7 +87,7 @@ Thanks everyone! :question: If you have a **question**, please check if it is already answered in the [**FAQ**](https://json.nlohmann.me/home/faq/) or the [**Q&A**](https://github.com/nlohmann/json/discussions/categories/q-a) section. If not, please [**ask a new question**](https://github.com/nlohmann/json/discussions/new) there. -: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/docs/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/). @@ -93,7 +97,7 @@ There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/t ## Examples -Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)). +Beside the examples below, you may want to check the [documentation](https://json.nlohmann.me/) where each function contains a separate code example (e.g., check out [`emplace()`](https://json.nlohmann.me/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/docs/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/docs/examples/emplace.cpp)). ### JSON as first-class data type @@ -162,7 +166,7 @@ json j2 = { }; ``` -Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://nlohmann.github.io/json/api/basic_json/array/) and [`json::object()`](https://nlohmann.github.io/json/api/basic_json/object/) will help: +Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://json.nlohmann.me/api/basic_json/array/) and [`json::object()`](https://json.nlohmann.me/api/basic_json/object/) will help: ```cpp // a way to express the empty array [] @@ -197,7 +201,7 @@ auto j2 = R"( Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. -The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/api/basic_json/parse/): +The above example can also be expressed explicitly using [`json::parse()`](https://json.nlohmann.me/api/basic_json/parse/): ```cpp // parse explicitly @@ -240,9 +244,9 @@ std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) -* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. +* In function `from_json`, use function [`at()`](https://json.nlohmann.me/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. #### Simplify your life with macros @@ -857,7 +861,7 @@ namespace nlohmann { #### Can I write my own serializer? (Advanced use) -Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples. +Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-udt.cpp) in the test suite, to see a few examples. If you write your own serializer, you'll need to do a few things: @@ -961,9 +965,9 @@ Other Important points: - When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. - If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. -### Binary formats (BSON, CBOR, MessagePack, and UBJSON) +### Binary formats (BSON, CBOR, MessagePack, UBJSON, and BJData) -Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](https://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), and [UBJSON](https://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors. +Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](https://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), [UBJSON](https://ubjson.org) (Universal Binary JSON Specification) and [BJData](https://neurojson.org/bjdata) (Binary JData) to efficiently encode JSON values to byte vectors and to decode such vectors. ```cpp // create a JSON value @@ -1083,18 +1087,11 @@ The following compilers are currently used in continuous integration at [AppVeyo | Apple Clang 12.0.0 (clang-1200.0.32.27); Xcode 12.2 | macOS 10.15.7 | GitHub Actions | | Apple Clang 12.0.0 (clang-1200.0.32.28); Xcode 12.3 | macOS 10.15.7 | GitHub Actions | | Apple Clang 12.0.0 (clang-1200.0.32.29); Xcode 12.4 | macOS 10.15.7 | GitHub Actions | -| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.12) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 6.4.0 (Ubuntu 6.4.0-17ubuntu1) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 7.5.0 (Ubuntu 7.5.0-6ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | -| GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | -| GCC 8.4.0 (Ubuntu 8.4.0-3ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 11.1.0 | Ubuntu (aarch64) | Drone CI | -| GCC 12.0.0 20211219 (experimental) | Ubuntu 20.04.3 LTS | GitHub Actions | +| Apple Clang 13.0.0 (clang-1300.0.29.3); Xcode 13.1 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.0.0 (clang-1300.0.29.30); Xcode 13.2 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.0.0 (clang-1300.0.29.30); Xcode 13.2.1 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.1.6 (clang-1316.0.21.2); Xcode 13.3 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.1.6 (clang-1316.0.21.2.3); Xcode 13.3.1 | macOS 12.3.1 | GitHub Actions | | Clang 3.5.2 (3.5.2-3ubuntu1) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 3.6.2 (3.6.2-3ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 3.7.1 (3.7.1-2ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | @@ -1113,8 +1110,22 @@ The following compilers are currently used in continuous integration at [AppVeyo | Clang 11.0.0 (11.0.0-2~ubuntu20.04.1) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 12.0.0 (12.0.0-3ubuntu1~20.04.3) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 13.0.1 (13.0.1-++20211015123032+cf15ccdeb6d5-1exp120211015003613.5) | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 14.0.0 (14.0.0-++20211221052852+55c71c9eac9b-1exp120211221172954.95) | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 15.0.0 (15.0.0-++20220403052648+896770c9a92e-1~exp1~20220403172744.209) | Ubuntu 20.04.3 LTS | GitHub Actions | +| Clang 14.0.5-++20220603124341+2f0a69c32a4c-1~exp1~20220603124352.149 | Ubuntu 20.04.3 LTS | GitHub Actions | +| Clang 15.0.0 (15.0.0-++20220530052901+b7d2b160c3ba-1~exp1~20220530172952.268) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.12) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 6.4.0 (Ubuntu 6.4.0-17ubuntu1) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 7.5.0 (Ubuntu 7.5.0-6ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | +| GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | +| GCC 8.4.0 (Ubuntu 8.4.0-3ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 11.1.0 | Ubuntu (aarch64) | Drone CI | +| GCC 11.1.0 (Ubuntu 11.1.0-1ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 13.0.0 13.0.0 20220605 (experimental) | Ubuntu 20.04.3 LTS | GitHub Actions | +| Intel C++ Compiler 2021.5.0.20211109 | Ubuntu 20.04.3 LTS | GitHub Actions | | NVCC 11.0.221 | Ubuntu 20.04.3 LTS | GitHub Actions | | Visual Studio 14 2015 MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor | | Visual Studio 15 2017 MSVC 19.16.27035.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor | @@ -1329,7 +1340,7 @@ Only if your request would contain confidential information, please [send me an I deeply appreciate the help of the following people. - + - [Teemperor](https://github.com/Teemperor) implemented CMake support and lcov integration, realized escape and Unicode handling in the string parser, and fixed the JSON serialization. - [elliotgoodrich](https://github.com/elliotgoodrich) fixed an issue with double deletion in the iterator classes. @@ -1598,6 +1609,21 @@ I deeply appreciate the help of the following people. - [Dirk Stolle](https://github.com/striezel) fixed typos in documentation. - [Daniel Albuschat](https://github.com/daniel-kun) corrected the parameter name in the `parse` documentation. - [Prince Mendiratta](https://github.com/Prince-Mendiratta) fixed a link to the FAQ. +- [Florian Albrechtskirchinger](https://github.com/falbrechtskirchinger) implemented `std::string_view` support for object keys and made dozens of other improvements. +- [Qianqian Fang](https://github.com/fangq) implemented the Binary JData (BJData) format. +- [pketelsen](https://github.com/pketelsen) added macros `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` and `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`. +- [DarkZeros](https://github.com/DarkZeros) adjusted to code to not clash with Arduino defines. +- [flagarde](https://github.com/flagarde) fixed the output of `meta()` for MSVC. +- [Giovanni Cerretani](https://github.com/gcerretani) fixed a check for `std::filesystem`. +- [Dimitris Apostolou](https://github.com/rex4539) fixed a typo. +- [Ferry Huberts](https://github.com/fhuberts) fixed a typo. +- [Michael Nosthoff](https://github.com/heinemml) fixed a typo. +- [JungHoon Lee](https://github.com/jhnlee) fixed a typo. +- [Faruk D.](https://github.com/fdiblen) fixed the CITATION.CFF file. +- [Andrea Cocito](https://github.com/puffetto) added a clarification on macro usage to the documentation. +- [Krzysiek Karbowiak](https://github.com/kkarbowiak) refactored the tests to use `CHECK_THROWS_WITH_AS`. +- [Chaoqi Zhang](https://github.com/prncoprs) fixed a typo. +- [ivanovmp](https://github.com/ivanovmp) fixed a whitespace error. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. @@ -1612,7 +1638,7 @@ The library itself consists of a single header file licensed under the MIT licen - [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code indentation - [**Clang**](https://clang.llvm.org) for compilation with code sanitizers - [**CMake**](https://cmake.org) for build automation -- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) +- [**Codacy**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) - [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/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 @@ -1632,7 +1658,7 @@ The library itself consists of a single header file licensed under the MIT licen ## Projects using JSON for Modern C++ -The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. +The library is currently used in Apple macOS Sierra-Monterey and iOS 10-15. I am not sure what they are using the library for, but I am happy that it runs on so many devices. ## Notes @@ -1647,7 +1673,7 @@ The library supports **Unicode input** as follows: - [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. -- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers. +- When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers. - To store wide strings (e.g., `std::wstring`), you need to convert them to a UTF-8 encoded `std::string` before, see [an example](https://json.nlohmann.me/home/faq/#wide-string-handling). ### Comments in JSON @@ -1682,7 +1708,7 @@ Here is a related issue [#1924](https://github.com/nlohmann/json/issues/1924). ### Further notes -- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`. +- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://json.nlohmann.me/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://json.nlohmann.me/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`. - As the exact number type is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions. - The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. - **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). diff --git a/cmake/ci.cmake b/cmake/ci.cmake index be564fa99..4fcff86aa 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -111,7 +111,7 @@ set(CLANG_CXXFLAGS -Wno-reserved-identifier ) -# Warning flags determined for GCC 12.0 (experimental) with https://github.com/nlohmann/gcc_flags: +# Warning flags determined for GCC 13.0 (experimental) with https://github.com/nlohmann/gcc_flags: # Ignored GCC warnings: # -Wno-abi-tag We do not care about ABI tags. # -Wno-aggregate-return The library uses aggregate returns. @@ -161,10 +161,13 @@ set(GCC_CXXFLAGS -Wanalyzer-use-after-free -Wanalyzer-use-of-pointer-in-stale-stack-frame -Wanalyzer-use-of-uninitialized-value + -Wanalyzer-va-arg-type-mismatch + -Wanalyzer-va-list-exhausted + -Wanalyzer-va-list-leak + -Wanalyzer-va-list-use-after-va-end -Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal -Warith-conversion - -Warray-bounds -Warray-bounds=2 -Warray-compare -Warray-parameter=2 @@ -209,6 +212,7 @@ set(GCC_CXXFLAGS -Wctad-maybe-unsupported -Wctor-dtor-privacy -Wdangling-else + -Wdangling-pointer=2 -Wdate-time -Wdelete-incomplete -Wdelete-non-virtual-dtor @@ -279,6 +283,7 @@ set(GCC_CXXFLAGS -Wmissing-include-dirs -Wmissing-profile -Wmissing-requires + -Wmissing-template-keyword -Wmultichar -Wmultiple-inheritance -Wmultistatement-macros @@ -340,11 +345,9 @@ set(GCC_CXXFLAGS -Wsizeof-pointer-div -Wsizeof-pointer-memaccess -Wstack-protector - -Wstrict-aliasing -Wstrict-aliasing=3 -Wstrict-null-sentinel - -Wstrict-overflow - -Wstrict-overflow=5 + -Wno-strict-overflow -Wstring-compare -Wstringop-overflow=4 -Wstringop-overread @@ -373,6 +376,7 @@ set(GCC_CXXFLAGS -Wterminate -Wtrampolines -Wtrigraphs + -Wtrivial-auto-var-init -Wtsan -Wtype-limits -Wundef @@ -392,6 +396,7 @@ set(GCC_CXXFLAGS -Wunused-result -Wunused-value -Wunused-variable + -Wuse-after-free=3 -Wuseless-cast -Wvarargs -Wvariadic-macros @@ -411,7 +416,7 @@ set(GCC_CXXFLAGS add_custom_target(ci_test_gcc COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -421,7 +426,7 @@ add_custom_target(ci_test_gcc add_custom_target(ci_test_clang COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang COMMAND cd ${PROJECT_BINARY_DIR}/build_clang && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -463,7 +468,7 @@ endforeach() add_custom_target(ci_test_noexceptions COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DCMAKE_CXX_FLAGS=-DJSON_NOEXCEPTION -DDOCTEST_TEST_FILTER=--no-throw + -DJSON_BuildTests=ON -DCMAKE_CXX_FLAGS=-DJSON_NOEXCEPTION -DDOCTEST_TEST_FILTER=--no-throw -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noexceptions COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noexceptions COMMAND cd ${PROJECT_BINARY_DIR}/build_noexceptions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -477,7 +482,7 @@ add_custom_target(ci_test_noexceptions add_custom_target(ci_test_noimplicitconversions COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_ImplicitConversions=OFF + -DJSON_BuildTests=ON -DJSON_ImplicitConversions=OFF -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noimplicitconversions COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noimplicitconversions COMMAND cd ${PROJECT_BINARY_DIR}/build_noimplicitconversions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -491,13 +496,27 @@ add_custom_target(ci_test_noimplicitconversions add_custom_target(ci_test_diagnostics COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_Diagnostics=ON + -DJSON_BuildTests=ON -DJSON_Diagnostics=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_diagnostics COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_diagnostics COMMAND cd ${PROJECT_BINARY_DIR}/build_diagnostics && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMENT "Compile and test with improved diagnostics enabled" ) +############################################################################### +# Enable legacy discarded value comparison. +############################################################################### + +add_custom_target(ci_test_legacycomparison + COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_LegacyDiscardedValueComparison=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_legacycomparison + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_legacycomparison + COMMAND cd ${PROJECT_BINARY_DIR}/build_legacycomparison && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMENT "Compile and test with legacy discarded value comparison enabled" +) + ############################################################################### # Coverage. ############################################################################### @@ -505,14 +524,21 @@ add_custom_target(ci_test_diagnostics add_custom_target(ci_test_coverage COMMAND CXX=g++ ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="--coverage;-fprofile-arcs;-ftest-coverage" - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMAND CXX=g++ ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="-m32;--coverage;-fprofile-arcs;-ftest-coverage" + -DJSON_BuildTests=ON -DJSON_32bitTest=ONLY + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage32 + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage32 + COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage32 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc lcov_branch_coverage=1 COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc lcov_branch_coverage=1 - COMMAND ${CMAKE_SOURCE_DIR}/test/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept + COMMAND ${CMAKE_SOURCE_DIR}/tests/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept COMMENT "Compile and test with coverage" @@ -542,16 +568,16 @@ set(ASTYLE_FLAGS --style=allman --indent=spaces=4 --indent-modifiers --indent-sw file(GLOB_RECURSE INDENT_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp - ${PROJECT_SOURCE_DIR}/test/src/*.cpp - ${PROJECT_SOURCE_DIR}/test/src/*.hpp - ${PROJECT_SOURCE_DIR}/benchmarks/src/benchmarks.cpp - ${PROJECT_SOURCE_DIR}/doc/examples/*.cpp + ${PROJECT_SOURCE_DIR}/tests/src/*.cpp + ${PROJECT_SOURCE_DIR}/tests/src/*.hpp + ${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp + ${PROJECT_SOURCE_DIR}/docs/examples/*.cpp ) add_custom_target(ci_test_amalgamation COMMAND rm -fr ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~ COMMAND cp ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~ - COMMAND ${Python3_EXECUTABLE} ${PROJECT_SOURCE_DIR}/third_party/amalgamate/amalgamate.py -c ${PROJECT_SOURCE_DIR}/third_party/amalgamate/config.json -s . + COMMAND ${Python3_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/amalgamate/amalgamate.py -c ${PROJECT_SOURCE_DIR}/tools/amalgamate/config.json -s . COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} --suffix=none --quiet ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp COMMAND diff ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~ ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp @@ -559,7 +585,21 @@ add_custom_target(ci_test_amalgamation COMMAND cd ${PROJECT_SOURCE_DIR} && for FILE in `find . -name '*.orig'`\; do false \; done WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - COMMENT "Check amalagamation and indentation" + COMMENT "Check amalgamation and indentation" +) + +############################################################################### +# Build and test using the amalgamated header +############################################################################### + +add_custom_target(ci_test_single_header + COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_MultipleHeader=OFF -DJSON_FastTests=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_single_header + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_single_header + COMMAND cd ${PROJECT_BINARY_DIR}/build_single_header && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMENT "Compile and test single-header version" ) ############################################################################### @@ -605,7 +645,7 @@ add_custom_target(ci_cppcheck ############################################################################### add_custom_target(ci_cpplint - COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/third_party/cpplint/cpplint.py --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES} + COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/cpplint/cpplint.py --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES} COMMENT "Check code with cpplint" ) @@ -645,7 +685,7 @@ add_custom_target(ci_clang_tidy COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_CLANG_TIDY=${CLANG_TIDY_TOOL} - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_tidy COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_tidy COMMENT "Check code with Clang-Tidy" @@ -672,7 +712,7 @@ add_custom_target(ci_pvs_studio add_custom_target(ci_infer COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer - COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run -- make COMMENT "Check code with Infer" ) @@ -683,7 +723,7 @@ add_custom_target(ci_infer add_custom_target(ci_offline_testdata COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data - COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data && ${GIT_TOOL} clone -c advice.detachedHead=false --branch v3.0.0 https://github.com/nlohmann/json_test_data.git --quiet --depth 1 + COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data && ${GIT_TOOL} clone -c advice.detachedHead=false --branch v3.1.0 https://github.com/nlohmann/json_test_data.git --quiet --depth 1 COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_TestDataDirectory=${PROJECT_BINARY_DIR}/build_offline_testdata/test_data/json_test_data @@ -698,6 +738,7 @@ add_custom_target(ci_offline_testdata ############################################################################### add_custom_target(ci_non_git_tests + COMMAND git config --global --add safe.directory ${PROJECT_SOURCE_DIR} COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_non_git_tests/sources COMMAND cd ${PROJECT_SOURCE_DIR} && for FILE in `${GIT_TOOL} ls-tree --name-only HEAD`\; do cp -r $$FILE ${PROJECT_BINARY_DIR}/build_non_git_tests/sources \; done COMMAND ${CMAKE_COMMAND} @@ -797,8 +838,9 @@ endfunction() ci_get_cmake(3.1.0 CMAKE_3_1_0_BINARY) ci_get_cmake(3.13.0 CMAKE_3_13_0_BINARY) -set(JSON_CMAKE_FLAGS_3_1_0 "JSON_Install;JSON_MultipleHeaders;JSON_ImplicitConversions;JSON_Valgrind;JSON_Diagnostics;JSON_SystemInclude") -set(JSON_CMAKE_FLAGS_3_13_0 "JSON_BuildTests") +set(JSON_CMAKE_FLAGS_3_1_0 JSON_Diagnostics JSON_ImplicitConversions JSON_DisableEnumSerialization + JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind) +set(JSON_CMAKE_FLAGS_3_13_0 JSON_BuildTests) function(ci_add_cmake_flags_targets flag min_version) string(TOLOWER "ci_cmake_flag_${flag}" flag_target) @@ -841,7 +883,7 @@ add_custom_target(ci_cmake_flags # Use more installed compilers. ############################################################################### -foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14) +foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14) find_program(COMPILER_TOOL NAMES ${COMPILER}) if (COMPILER_TOOL) if ("${COMPILER}" STREQUAL "clang++-9") @@ -873,10 +915,25 @@ add_custom_target(ci_cuda_example COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CUDA_HOST_COMPILER=g++-8 - -S${PROJECT_SOURCE_DIR}/test/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example + -S${PROJECT_SOURCE_DIR}/tests/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_cuda_example ) +############################################################################### +# Intel C++ Compiler +############################################################################### + +add_custom_target(ci_icpc + COMMAND ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc + -DJSON_BuildTests=ON -DJSON_FastTests=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_icpc + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_icpc + COMMAND cd ${PROJECT_BINARY_DIR}/build_icpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure + COMMENT "Compile and test with ICPC" +) + ############################################################################### # Clean up all generated files. ############################################################################### diff --git a/cmake/download_test_data.cmake b/cmake/download_test_data.cmake index f516a7c3b..1bb998dae 100644 --- a/cmake/download_test_data.cmake +++ b/cmake/download_test_data.cmake @@ -1,5 +1,5 @@ set(JSON_TEST_DATA_URL https://github.com/nlohmann/json_test_data) -set(JSON_TEST_DATA_VERSION 3.0.0) +set(JSON_TEST_DATA_VERSION 3.1.0) # if variable is set, use test data from given directory rather than downloading them if(JSON_TestDataDirectory) diff --git a/cmake/test.cmake b/cmake/test.cmake index 1d146646b..b8b1250fb 100644 --- a/cmake/test.cmake +++ b/cmake/test.cmake @@ -156,6 +156,7 @@ endfunction() ############################################################################# # json_test_add_test_for( # +# [NAME ] # MAIN
# [CXX_STANDARDS ...] [FORCE]) # @@ -165,6 +166,7 @@ endfunction() # # if C++ standard is supported by the compiler and the # source file contains JSON_HAS_CPP_. +# Use NAME to override the filename-derived test name. # Use FORCE to create the test regardless of the file containing # JSON_HAS_CPP_. # Test targets are linked against
. @@ -172,15 +174,22 @@ endfunction() ############################################################################# 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}) + cmake_parse_arguments(args "FORCE" "MAIN;NAME" "CXX_STANDARDS" ${ARGN}) if("${args_MAIN}" STREQUAL "") message(FATAL_ERROR "Required argument MAIN
missing.") endif() + if("${args_NAME}" STREQUAL "") + get_filename_component(file_basename ${file} NAME_WE) + string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename}) + else() + set(test_name ${args_NAME}) + if(NOT test_name MATCHES "test-[^$]+") + message(FATAL_ERROR "Test name must start with 'test-'.") + endif() + endif() + if("${args_CXX_STANDARDS}" STREQUAL "") set(args_CXX_STANDARDS 11) endif() @@ -202,3 +211,32 @@ function(json_test_add_test_for file) _json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard}) endforeach() endfunction() + +############################################################################# +# json_test_should_build_32bit_test( +# ) +# +# Check if the 32bit unit test should be built based on the value of +# and store the result in the variables and +# . +############################################################################# + +function(json_test_should_build_32bit_test build_32bit_var build_32bit_only_var input) + set(${build_32bit_only_var} OFF PARENT_SCOPE) + string(TOUPPER "${input}" ${build_32bit_var}) + if("${${build_32bit_var}}" STREQUAL AUTO) + # check if compiler is targeting 32bit by default + include(CheckTypeSize) + check_type_size("size_t" sizeof_size_t LANGUAGE CXX) + if(sizeof_size_t AND ${sizeof_size_t} EQUAL 4) + message(STATUS "Auto-enabling 32bit unit test.") + set(${build_32bit_var} ON) + else() + set(${build_32bit_var} OFF) + endif() + elseif("${${build_32bit_var}}" STREQUAL ONLY) + set(${build_32bit_only_var} ON PARENT_SCOPE) + endif() + + set(${build_32bit_var} "${${build_32bit_var}}" PARENT_SCOPE) +endfunction() diff --git a/doc/examples/iterator_wrapper.cpp b/doc/examples/iterator_wrapper.cpp deleted file mode 100644 index 84d37254b..000000000 --- a/doc/examples/iterator_wrapper.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -using json = nlohmann::json; - -int main() -{ - // create JSON values - json j_object = {{"one", 1}, {"two", 2}}; - json j_array = {1, 2, 4, 8, 16}; - - ////////////////////////////////////////////////////////////////////////// - // The static function iterator_wrapper was deprecated in version 3.1.0 - // and will be removed in version 4.0.0. Please replace all occurrences - // of iterator_wrapper(j) with j.items(). - ////////////////////////////////////////////////////////////////////////// - - // example for an object - for (auto& x : json::iterator_wrapper(j_object)) - { - std::cout << "key: " << x.key() << ", value: " << x.value() << '\n'; - } - - // example for an array - for (auto& x : json::iterator_wrapper(j_array)) - { - std::cout << "key: " << x.key() << ", value: " << x.value() << '\n'; - } -} diff --git a/doc/examples/iterator_wrapper.output b/doc/examples/iterator_wrapper.output deleted file mode 100644 index 89b09f524..000000000 --- a/doc/examples/iterator_wrapper.output +++ /dev/null @@ -1,7 +0,0 @@ -key: one, value: 1 -key: two, value: 2 -key: 0, value: 1 -key: 1, value: 2 -key: 2, value: 4 -key: 3, value: 8 -key: 4, value: 16 diff --git a/doc/examples/sax_parse.output b/doc/examples/sax_parse.output deleted file mode 100644 index e16c2c4de..000000000 --- a/doc/examples/sax_parse.output +++ /dev/null @@ -1,2 +0,0 @@ -(start: object) (key: Image) (start: object) (key: Width) (value: 800) (key: Height) (value: 600) (key: Title) (value: View from 15th Floor) (key: Thumbnail) (start: object) (key: Url) (value: http://www.example.com/image/481989943) (key: Height) (value: 125) (key: Width) (value: 100) (end: object) (key: Animated) (value: false) (key: IDs) (start: array) (value: 116) (value: 943) (value: 234) (value: 38793) (end: array) (key: Distance) (value: 12.723374634) (end: object) (end: object) -result: true diff --git a/doc/mkdocs/docs/api/basic_json/count.md b/doc/mkdocs/docs/api/basic_json/count.md deleted file mode 100644 index fcfef8673..000000000 --- a/doc/mkdocs/docs/api/basic_json/count.md +++ /dev/null @@ -1,55 +0,0 @@ -# nlohmann::basic_json::count - -```cpp -template -size_type count(KeyT&& key) const; -``` - -Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will -always be `0` (`key` was not found) or `1` (`key` was found). - -## Template parameters - -`KeyT` -: A type for an object key. - -## Parameters - -`key` (in) -: key value of the element to count. - -## Return value - -Number of elements with key `key`. If the JSON value is not an object, the return value will be `0`. - -## Exception safety - -Strong exception safety: if an exception occurs, the original value stays intact. - -## Complexity - -Logarithmic in the size of the JSON object. - -## Notes - -This method always returns `0` when executed on a JSON type that is not an object. - -## Examples - -??? example - - The example shows how `count()` is used. - - ```cpp - --8<-- "examples/count.cpp" - ``` - - Output: - - ```json - --8<-- "examples/count.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/find.md b/doc/mkdocs/docs/api/basic_json/find.md deleted file mode 100644 index af4cb2972..000000000 --- a/doc/mkdocs/docs/api/basic_json/find.md +++ /dev/null @@ -1,63 +0,0 @@ -# nlohmann::basic_json::find - -```cpp -template -iterator find(KeyT&& key); - -template -const_iterator find(KeyT&& key) const; -``` - -Finds an element in a JSON object with key equivalent to `key`. If the element is not found or the JSON value is not an -object, `end()` is returned. - -## Template parameters - -`KeyT` -: A type for an object key. - -## Parameters - -`key` (in) -: key value of the element to search for. - -## Return value - -Iterator to an element with key equivalent to `key`. If no such element is found or the JSON value is not an object, -past-the-end (see `end()`) iterator is returned. - -## Exception safety - -Strong exception safety: if an exception occurs, the original value stays intact. - -## Complexity - -Logarithmic in the size of the JSON object. - -## Notes - -This method always returns `end()` when executed on a JSON type that is not an object. - -## Examples - -??? example - - The example shows how `find()` is used. - - ```cpp - --8<-- "examples/find__key_type.cpp" - ``` - - Output: - - ```json - --8<-- "examples/find__key_type.output" - ``` - -## See also - -- [contains](contains.md) checks whether a key exists - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/get_allocator.md b/doc/mkdocs/docs/api/basic_json/get_allocator.md deleted file mode 100644 index 1b7700c77..000000000 --- a/doc/mkdocs/docs/api/basic_json/get_allocator.md +++ /dev/null @@ -1,19 +0,0 @@ -# nlohmann::basic_json::get_allocator - -```cpp -static allocator_type get_allocator(); -``` - -Returns the allocator associated with the container. - -## Return value - -associated allocator - -## Version history - -- Unknown. - -!!! note - - This documentation page is a stub. diff --git a/doc/mkdocs/docs/api/basic_json/object_comparator_t.md b/doc/mkdocs/docs/api/basic_json/object_comparator_t.md deleted file mode 100644 index 44509a94b..000000000 --- a/doc/mkdocs/docs/api/basic_json/object_comparator_t.md +++ /dev/null @@ -1,16 +0,0 @@ -# nlohmann::basic_json::object_comparator_t - -```cpp -using object_comparator_t = std::less; // until C++14 - -using object_comparator_t = std::less<>; // since C++14 -``` - -The comparator used in [`object_t`](object_t.md). - -When C++14 is detected, a transparent com parator is used which, when combined with perfect forwarding on find() and -count() calls, prevents unnecessary string construction. - -## Version history - -- Unknown. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ValueType.md b/doc/mkdocs/docs/api/basic_json/operator_ValueType.md deleted file mode 100644 index 1eec13553..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_ValueType.md +++ /dev/null @@ -1,72 +0,0 @@ -# nlohmann::basic_json::operator ValueType - -```cpp -template -JSON_EXPLICIT operator ValueType() const; -``` - -Implicit type conversion between the JSON value and a compatible value. The call is realized by calling -[`get()`](get.md). See [Notes](#notes) for the meaning of `JSON_EXPLICIT`. - -## Template parameters - -`ValueType` -: the value type to return - -## Return value - -copy of the JSON value, converted to `ValueType` - -## Exceptions - -Depends on what `json_serializer` `from_json()` method throws - -## Complexity - -Linear in the size of the JSON value. - -## Notes - -By default `JSON_EXPLICIT` defined to the empty string, so the signature is: - -```cpp -template -operator ValueType() const; -``` - -If [`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) is set to `0`, -`JSON_EXPLICIT` is defined to `#!cpp explicit`: - -```cpp -template -explicit operator ValueType() const; -``` - -That is, implicit conversions can be switched off by defining -[`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) to `0`. - -## Examples - -??? example - - The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers, (2) A JSON array can be converted to a standard - `std::vector`, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`. - - ```cpp - --8<-- "examples/operator__ValueType.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__ValueType.output" - ``` - -## Version history - -- Since version 1.0.0. -- Macros `JSON_EXPLICIT`/[`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) added - in version 3.9.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ge.md b/doc/mkdocs/docs/api/basic_json/operator_ge.md deleted file mode 100644 index 68aac6557..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_ge.md +++ /dev/null @@ -1,59 +0,0 @@ -# nlohmann::basic_json::operator>= - -```cpp -bool operator>=(const_reference lhs, const_reference rhs) noexcept, - -template -bool operator>=(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator>=(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is greater than or equal to another JSON value `rhs` by calculating -`#!cpp !(lhs < rhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is less than or equal to `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__greaterequal.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__greaterequal.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_gt.md b/doc/mkdocs/docs/api/basic_json/operator_gt.md deleted file mode 100644 index 92ec30594..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_gt.md +++ /dev/null @@ -1,58 +0,0 @@ -# nlohmann::basic_json::operator> - -```cpp -bool operator>(const_reference lhs, const_reference rhs) noexcept, - -template -bool operator>(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator>(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is greater than another JSON value `rhs` by calculating `#!cpp !(lhs <= rhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is greater than `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__greater.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__greater.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_le.md b/doc/mkdocs/docs/api/basic_json/operator_le.md deleted file mode 100644 index 54f9a2809..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_le.md +++ /dev/null @@ -1,59 +0,0 @@ -# nlohmann::basic_json::operator<= - -```cpp -bool operator<=(const_reference lhs, const_reference rhs) noexcept, - -template -bool operator<=(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator<=(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is less than or equal to another JSON value `rhs` by calculating -`#cpp !(rhs < lhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is less than or equal to `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__lessequal.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__lessequal.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_lt.md b/doc/mkdocs/docs/api/basic_json/operator_lt.md deleted file mode 100644 index d1a4999b4..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_lt.md +++ /dev/null @@ -1,73 +0,0 @@ -# nlohmann::basic_json::operator< - -```cpp -bool operator<(const_reference lhs, const_reference rhs) noexcept; - -template -bool operator<(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator<(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is less than another JSON value `rhs` according to the following rules: - -- If `lhs` and `rhs` have the same type, the values are compared using the default `<` operator. -- Integer and floating-point numbers are automatically converted before comparison -- Discarded values a -- In case `lhs` and `rhs` have different types, the values are ignored and the order of the types is considered, which - is: - 1. null - 2. boolean - 3. number (all types) - 4. object - 5. array - 6. string - 7. binary - - For instance, any boolean value is considered less than any string. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is less than `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__less.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__less.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ne.md b/doc/mkdocs/docs/api/basic_json/operator_ne.md deleted file mode 100644 index e94da9b76..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_ne.md +++ /dev/null @@ -1,72 +0,0 @@ -# nlohmann::basic_json::operator!= - -```cpp -bool operator!=(const_reference lhs, const_reference rhs) noexcept; - -template -bool operator!=(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator!=(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares two JSON values for inequality by calculating `#!cpp !(lhs == rhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether the values `lhs` and `rhs` are not equal - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__notequal.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__notequal.output" - ``` - -??? example - - The example demonstrates comparing several JSON types against the null pointer (JSON `#!json null`). - - ```cpp - --8<-- "examples/operator__notequal__nullptr_t.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__notequal__nullptr_t.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/value_t.md b/doc/mkdocs/docs/api/basic_json/value_t.md deleted file mode 100644 index 768b13ca1..000000000 --- a/doc/mkdocs/docs/api/basic_json/value_t.md +++ /dev/null @@ -1,36 +0,0 @@ -# nlohmann::basic_json::value_t - -```cpp -enum class value_t : std::uint8_t { - null, - object, - array, - string, - boolean, - number_integer, - number_unsigned, - number_float, - binary, - discarded -}; -``` - -This enumeration collects the different JSON types. It is internally used to distinguish the stored values, and the -functions [`is_null`](is_null.md), [`is_object`](is_object.md), [`is_array`](is_array.md), [`is_string`](is_string.md), -[`is_boolean`](is_boolean.md), [`is_number`](is_number.md) (with [`is_number_integer`](is_number_integer.md), -[`is_number_unsigned`](is_number_unsigned.md), and [`is_number_float`](is_number_float.md)), -[`is_discarded`](is_discarded.md), [`is_binary`](is_binary.md), [`is_primitive`](is_primitive.md), and -[`is_structured`](is_structured.md) rely on it. - -## Notes - -There are three enumeration entries (number_integer, number_unsigned, and number_float), because the library -distinguishes these three types for numbers: [`number_unsigned_t`](number_unsigned_t.md) is used for unsigned integers, -[`number_integer_t`](number_integer_t.md) is used for signed integers, and [`number_float_t`](number_float_t.md) is used -for floating-point numbers or to approximate integers which do not fit in the limits of their respective type. - -## Version history - -- Added in version 1.0.0. -- Added unsigned integer type in version 2.0.0. -- Added binary type in version 3.8.0. diff --git a/doc/mkdocs/docs/api/json_sax/end_array.md b/doc/mkdocs/docs/api/json_sax/end_array.md deleted file mode 100644 index 245cf974c..000000000 --- a/doc/mkdocs/docs/api/json_sax/end_array.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::json_sax::end_array - -```cpp -virtual bool end_array() = 0; -``` - -The end of an array was read. - -## Return value - -Whether parsing should proceed. - -## Version history - -- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/end_object.md b/doc/mkdocs/docs/api/json_sax/end_object.md deleted file mode 100644 index 5654e262e..000000000 --- a/doc/mkdocs/docs/api/json_sax/end_object.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::json_sax::end_object - -```cpp -virtual bool end_object() = 0; -``` - -The end of an object was read. - -## Return value - -Whether parsing should proceed. - -## Version history - -- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/null.md b/doc/mkdocs/docs/api/json_sax/null.md deleted file mode 100644 index bcbb4a348..000000000 --- a/doc/mkdocs/docs/api/json_sax/null.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::json_sax::null - -```cpp -virtual bool null() = 0; -``` - -A null value was read. - -## Return value - -Whether parsing should proceed. - -## Version history - -- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/macros/index.md b/doc/mkdocs/docs/api/macros/index.md deleted file mode 100644 index 4c723c6a6..000000000 --- a/doc/mkdocs/docs/api/macros/index.md +++ /dev/null @@ -1,22 +0,0 @@ -# Macros - -!!! note - - This page is under construction. See the [macro overview page](../../features/macros.md) until then. - -Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header. - -- [`JSON_ASSERT(x)`](json_assert.md) -- `JSON_CATCH_USER(exception)` -- `JSON_DIAGNOSTICS` -- `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, `JSON_HAS_CPP_20` -- `JSON_NOEXCEPTION` -- `JSON_NO_IO` -- `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK` -- `JSON_THROW_USER(exception)` -- `JSON_TRY_USER` -- `JSON_USE_IMPLICIT_CONVERSIONS` -- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)` -- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)` -- `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` -- `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH` diff --git a/doc/mkdocs/docs/api/macros/json_assert.md b/doc/mkdocs/docs/api/macros/json_assert.md deleted file mode 100644 index 63d4ae076..000000000 --- a/doc/mkdocs/docs/api/macros/json_assert.md +++ /dev/null @@ -1,11 +0,0 @@ -# JSON_ASSERT(x) - -```cpp -JSON_ASSERT(x) -``` - -## Default implementation - -```cpp -assert(x); -``` diff --git a/doc/mkdocs/docs/api/ordered_json.md b/doc/mkdocs/docs/api/ordered_json.md deleted file mode 100644 index 8b122f90b..000000000 --- a/doc/mkdocs/docs/api/ordered_json.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::ordered_json - -```cpp -using ordered_json = basic_json; -``` - -This type preserves the insertion order of object keys. - -## See also - -- [ordered_map](ordered_map.md) - -## Version history - -Since version 3.9.0. diff --git a/doc/mkdocs/docs/features/element_access/checked_access.md b/doc/mkdocs/docs/features/element_access/checked_access.md deleted file mode 100644 index fd444bebe..000000000 --- a/doc/mkdocs/docs/features/element_access/checked_access.md +++ /dev/null @@ -1,77 +0,0 @@ -# Checked access: at - -## Overview - -The `#!cpp at()` member function performs checked access; that is, it returns a reference to the desired value if it exists and throws a [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) otherwise. - -??? example - - Consider the following JSON value: - - ```json - { - "name": "Mary Smith", - "age": 42, - "hobbies": ["hiking", "reading"] - } - ``` - - Assume the value is parsed to a `json` variable `j`. - - | expression | value | - | ---------- | ----- | - | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | - | `#!cpp j.at("name")` | `#!json "Mary Smith"` | - | `#!cpp j.at("age")` | `#!json 42` | - | `#!cpp j.at("hobbies")` | `#!json ["hiking", "reading"]` | - | `#!cpp j.at("hobbies").at(0)` | `#!json "hiking"` | - | `#!cpp j.at("hobbies").at(1)` | `#!json "reading"` | - -The return value is a reference, so it can be modified by the original value. - -??? example - - ```cpp - j.at("name") = "John Smith"; - ``` - - This code produces the following JSON value: - - ```json - { - "name": "John Smith", - "age": 42, - "hobbies": ["hiking", "reading"] - } - ``` - -When accessing an invalid index (i.e., an index greater than or equal to the array size) or the passed object key is non-existing, an exception is thrown. - -??? example - - ```cpp - j.at("hobbies").at(3) = "cooking"; - ``` - - This code produces the following exception: - - ``` - [json.exception.out_of_range.401] array index 3 is out of range - ``` - -## Notes - - -!!! failure "Exceptions" - - - `at` can only be used with objects (with a string argument) or with arrays (with a numeric argument). For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error304) is thrown. - - [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) exceptions are thrown if the provided key is not found in an object or the provided index is invalid. - -## Summary - -| scenario | non-const value | const value | -|-----------------------------------|------------------------------------------------|------------------------------------------------| -| access to existing object key | reference to existing value is returned | const reference to existing value is returned | -| access to valid array index | reference to existing value is returned | const reference to existing value is returned | -| access to non-existing object key | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | -| access to invalid array index | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | diff --git a/doc/mkdocs/docs/features/macros.md b/doc/mkdocs/docs/features/macros.md deleted file mode 100644 index 576ec935d..000000000 --- a/doc/mkdocs/docs/features/macros.md +++ /dev/null @@ -1,311 +0,0 @@ -# Supported Macros - -Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header. - -## `JSON_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) - ``` - -The macro was introduced in version 3.9.0. - -## `JSON_CATCH_USER(exception)` - -This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library. -The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range` -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. - -!!! 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) - ``` - -The macro was introduced in version 3.1.0. - -## `JSON_DIAGNOSTICS` - -This macro enables extended diagnostics for exception messages. Possible values are `1` to enable or `0` to disable -(default). - -When enabled, exception messages contain a [JSON Pointer](json_pointer.md) to the JSON value that triggered the -exception, see [Extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) for an example. Note -that enabling this macro increases the size of every JSON value by one pointer and adds some runtime overhead. - -The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets -`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 - ``` - -The macro was introduced in version 3.10.0. - -## `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` -support for C++17). For these new features, the library implements some preprocessor checks to determine the C++ -standard. By defining any of these symbols, the internal check is overridden and the provided C++ version is -unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be -detected incorrectly. - -!!! info "Default behavior" - - The default value is detected based on the preprocessor macros `#!cpp __cplusplus`, `#!cpp _HAS_CXX17`, or - `#!cpp _MSVC_LANG`. - -The macros were introduced in version 3.10.5. - -## `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 -for filesystem is limited, the library tries to detect whether ``/`std::filesystem` (`JSON_HAS_FILESYSTEM`) -or ``/`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`. - -!!! 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()`, or - `#!cpp __has_include()`. - -Note that older compilers or older versions of libstd++ also require the library `stdc++fs` to be linked to for -filesystem support. - -The macros were introduced in version 3.10.5. - -## `JSON_NOEXCEPTION` - -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 -`#!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`. - -Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not -available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). - -The macro was introduced in version 2.1.0. - -## `JSON_NO_IO` - -When defined, headers ``, ``, ``, ``, and `` are not included and parse functions -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)). - -!!! info "Default behavior" - - By default, the macro is not defined. - - ```cpp - #undef JSON_NO_IO - ``` - -The macro was introduced in version 3.10.0. - -## `JSON_SKIP_LIBRARY_VERSION_CHECK` - -When defined, the library will not create a compiler warning when a different version of the library was already -included. - -!!! info "Default behavior" - - By default, the macro is not defined. - - ```cpp - #undef JSON_SKIP_LIBRARY_VERSION_CHECK - ``` - -The macro was introduced in version 3.11.0. - -## `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 -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 - ``` - -The macro was introduced in version 3.2.0. - -## `JSON_THROW_USER(exception)` - -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 -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. - -The macro was introduced in version 3.1.0. - -## `JSON_TRY_USER` - -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. - -The macro was introduced in version 3.1.0. - -## `JSON_USE_IMPLICIT_CONVERSIONS` - -When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on. - -??? example - - This is an example for an implicit conversion: - - ```cpp - json j = "Hello, world!"; - std::string s = j; - ``` - - When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be - written like this: - - ```cpp - json j = "Hello, world!"; - auto s = j.get(); - ``` - -Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which -sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly. - -!!! info "Default behavior" - - ```cpp - #define JSON_USE_IMPLICIT_CONVERSIONS 1 - ``` - -The macro was introduced in version 3.9.0. - -## `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 -serialization and (2) want to use the member variable names as object keys in that object. - -The macro is to be defined inside the class/struct to create code for. Unlike -[`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members. -The first parameter is the name of the class/struct, and all remaining parameters name the members. - -See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. - -The macro was introduced in version 3.9.0. - -## `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. - -The macro was introduced in version 3.11.0. - -## `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 -serialization and (2) want to use the member variable names as object keys in that object. - -The macro is to be defined inside the namespace of the class/struct to create code for. Private members cannot be -accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios. The -first parameter is the name of the class/struct, and all remaining parameters name the members. - -See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. - -The macro was introduced in version 3.9.0. - -## `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. - -The macro was introduced in version 3.11.0. - -## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` - -This macro simplifies the serialization/deserialization of enum types. See -[Specializing enum conversion](enum_conversion.md) for more information. - -The macro was introduced in version 3.4.0. - -## `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH` - -These macros are defined by the library and contain the version numbers according to -[Semantic Versioning 2.0.0](https://semver.org). - -The macros were introduced in version 3.1.0. diff --git a/doc/mkdocs/requirements.txt b/doc/mkdocs/requirements.txt deleted file mode 100644 index b64e9b873..000000000 --- a/doc/mkdocs/requirements.txt +++ /dev/null @@ -1,29 +0,0 @@ -click>=7.1.2 -future>=0.18.2 -htmlmin>=0.1.12 -httplib2>=0.18.1 -importlib-metadata>=1.6.0 -Jinja2>=2.11.2 -joblib>=0.15.1 -jsmin>=2.2.2 -livereload>=2.6.1 -lunr>=0.5.8 -Markdown>=3.2.2 -markdown-include>=0.5.1 -MarkupSafe>=1.1.1 -mkdocs>=1.1.2 -mkdocs-material>=5.2.1 -mkdocs-material-extensions>=1.0 -mkdocs-minify-plugin>=0.3.0 -mkdocs-simple-hooks>=0.1.1 -nltk>=3.5 -plantuml>=0.3.0 -plantuml-markdown>=3.2.2 -Pygments>=2.6.1 -pymdown-extensions>=7.1 -PyYAML>=5.3.1 -regex>=2020.5.14 -six>=1.15.0 -tornado>=6.0.4 -tqdm>=4.46.0 -zipp>=3.1.0 diff --git a/doc/mkdocs/scripts/check_structure.py b/doc/mkdocs/scripts/check_structure.py deleted file mode 100644 index cacc51cb4..000000000 --- a/doc/mkdocs/scripts/check_structure.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python - -import glob -import os.path - - -def check_structure(): - expected_headers = [ - 'Template parameters', - 'Specializations', - 'Iterator invalidation', - 'Requirements', - 'Member types', - 'Member functions', - 'Member variables', - 'Static functions', - 'Non-member functions', - 'Literals', - 'Helper classes', - 'Parameters', - 'Return value', - 'Exception safety', - 'Exceptions', - 'Complexity', - 'Possible implementation', - 'Notes', - 'Examples', - 'See also', - 'Version history' - ] - - required_headers = [ - 'Examples', - 'Version history' - ] - - files = sorted(glob.glob('api/**/*.md', recursive=True)) - for file in files: - with open(file) as file_content: - header_idx = -1 - existing_headers = [] - in_initial_code_example = False - previous_line = None - h1sections = 0 - - for lineno, line in enumerate(file_content.readlines()): - line = line.strip() - - if line.startswith('# '): - h1sections += 1 - - # there should only be one top-level title - if h1sections > 1: - print(f'{file}:{lineno+1}: Error: unexpected top-level title "{line}"!') - h1sections = 1 - - # Overview pages should have a better title - if line == '# Overview': - print(f'{file}:{lineno+1}: Error: overview pages should have a better title!') - - # lines longer than 160 characters are bad (unless they are tables) - if len(line) > 160 and '|' not in line: - print(f'{file}:{lineno+1}: Error: line is too long ({len(line)} vs. 160 chars)!') - - # check if headers are correct - if line.startswith('## '): - header = line.strip('## ') - existing_headers.append(header) - - if header in expected_headers: - idx = expected_headers.index(header) - if idx <= header_idx: - print(f'{file}:{lineno+1}: Error: header "{header}" is in an unexpected order (should be before "{expected_headers[header_idx]}")!') - header_idx = idx - else: - print(f'{file}:{lineno+1}: Error: header "{header}" is not part of the expected headers!') - - # code example - if line == '```cpp' and header_idx == -1: - in_initial_code_example = True - - if in_initial_code_example and line.startswith('//'): - if any(map(str.isdigit, line)) and '(' not in line: - print(f'{file}:{lineno+1}: Number should be in parentheses: {line}') - - if line == '```' and in_initial_code_example: - in_initial_code_example = False - - # consecutive blank lines are bad - if line == '' and previous_line == '': - print(f'{file}:{lineno}-{lineno+1}: Error: Consecutive blank lines!') - - previous_line = line - - for required_header in required_headers: - if required_header not in existing_headers: - print(f'{file}:{lineno+1}: Error: required header "{required_header}" was not found!') - - -def check_examples(): - example_files = sorted(glob.glob('../../examples/*.cpp')) - markdown_files = sorted(glob.glob('**/*.md', recursive=True)) - - # check if every example file is used in at least one markdown file - for example_file in example_files: - example_file = os.path.join('examples', os.path.basename(example_file)) - - found = False - for markdown_file in markdown_files: - content = ' '.join(open(markdown_file).readlines()) - if example_file in content: - found = True - break - - if not found: - print(f'{example_file}: Error: example file is not used in any documentation file!') - - -if __name__ == '__main__': - check_structure() - check_examples() diff --git a/doc/Makefile b/docs/Makefile similarity index 100% rename from doc/Makefile rename to docs/Makefile diff --git a/doc/README.md b/docs/README.md similarity index 95% rename from doc/README.md rename to docs/README.md index ec5c25d49..b39d54e05 100644 --- a/doc/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ If you want to see the documentation for a specific tag or commit hash, you can git clone https://github.com/nlohmann/json.git cd json git checkout v3.10.2 -make install_venv serve -C doc/mkdocs +make install_venv serve -C docs/mkdocs ``` Open URL in your browser. Replace from any URL from the source code `https://json.nlohmann.me` diff --git a/doc/avatars.png b/docs/avatars.png similarity index 100% rename from doc/avatars.png rename to docs/avatars.png diff --git a/doc/docset/Info.plist b/docs/docset/Info.plist similarity index 100% rename from doc/docset/Info.plist rename to docs/docset/Info.plist diff --git a/doc/docset/Makefile b/docs/docset/Makefile similarity index 100% rename from doc/docset/Makefile rename to docs/docset/Makefile diff --git a/doc/docset/README.md b/docs/docset/README.md similarity index 100% rename from doc/docset/README.md rename to docs/docset/README.md diff --git a/doc/docset/docSet.sql b/docs/docset/docSet.sql similarity index 99% rename from doc/docset/docSet.sql rename to docs/docset/docSet.sql index 8bd4e0678..30c4a48de 100644 --- a/doc/docset/docSet.sql +++ b/docs/docset/docSet.sql @@ -140,6 +140,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('SAX Interface', 'Guide', 'fea INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'features/macros/index.html#json_assertx'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'features/macros/index.html#json_catch_userexception'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'features/macros/index.html#json_diagnostics'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'features/macros/index.html#json_disable_enum_serialization'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_11', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_17', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); diff --git a/doc/docset/docset.json b/docs/docset/docset.json similarity index 100% rename from doc/docset/docset.json rename to docs/docset/docset.json diff --git a/doc/docset/icon.png b/docs/docset/icon.png similarity index 100% rename from doc/docset/icon.png rename to docs/docset/icon.png diff --git a/doc/docset/icon@2x.png b/docs/docset/icon@2x.png similarity index 100% rename from doc/docset/icon@2x.png rename to docs/docset/icon@2x.png diff --git a/doc/examples/README.cpp b/docs/examples/README.cpp similarity index 100% rename from doc/examples/README.cpp rename to docs/examples/README.cpp diff --git a/doc/examples/README.output b/docs/examples/README.output similarity index 100% rename from doc/examples/README.output rename to docs/examples/README.output diff --git a/doc/examples/accept__string.cpp b/docs/examples/accept__string.cpp similarity index 100% rename from doc/examples/accept__string.cpp rename to docs/examples/accept__string.cpp diff --git a/doc/examples/accept__string.output b/docs/examples/accept__string.output similarity index 100% rename from doc/examples/accept__string.output rename to docs/examples/accept__string.output diff --git a/doc/examples/array.cpp b/docs/examples/array.cpp similarity index 100% rename from doc/examples/array.cpp rename to docs/examples/array.cpp diff --git a/doc/examples/array.output b/docs/examples/array.output similarity index 100% rename from doc/examples/array.output rename to docs/examples/array.output diff --git a/doc/examples/array_t.cpp b/docs/examples/array_t.cpp similarity index 100% rename from doc/examples/array_t.cpp rename to docs/examples/array_t.cpp diff --git a/doc/examples/array_t.output b/docs/examples/array_t.output similarity index 100% rename from doc/examples/array_t.output rename to docs/examples/array_t.output diff --git a/doc/examples/at__object_t_key_type.cpp b/docs/examples/at__object_t_key_type.cpp similarity index 100% rename from doc/examples/at__object_t_key_type.cpp rename to docs/examples/at__object_t_key_type.cpp diff --git a/doc/examples/at__object_t_key_type.output b/docs/examples/at__object_t_key_type.output similarity index 100% rename from doc/examples/at__object_t_key_type.output rename to docs/examples/at__object_t_key_type.output diff --git a/doc/examples/at__object_t_key_type_const.cpp b/docs/examples/at__object_t_key_type_const.cpp similarity index 100% rename from doc/examples/at__object_t_key_type_const.cpp rename to docs/examples/at__object_t_key_type_const.cpp diff --git a/doc/examples/at__object_t_key_type_const.output b/docs/examples/at__object_t_key_type_const.output similarity index 100% rename from doc/examples/at__object_t_key_type_const.output rename to docs/examples/at__object_t_key_type_const.output diff --git a/doc/examples/at__size_type.cpp b/docs/examples/at__size_type.cpp similarity index 100% rename from doc/examples/at__size_type.cpp rename to docs/examples/at__size_type.cpp diff --git a/doc/examples/at__size_type.output b/docs/examples/at__size_type.output similarity index 100% rename from doc/examples/at__size_type.output rename to docs/examples/at__size_type.output diff --git a/doc/examples/at__size_type_const.cpp b/docs/examples/at__size_type_const.cpp similarity index 100% rename from doc/examples/at__size_type_const.cpp rename to docs/examples/at__size_type_const.cpp diff --git a/doc/examples/at__size_type_const.output b/docs/examples/at__size_type_const.output similarity index 100% rename from doc/examples/at__size_type_const.output rename to docs/examples/at__size_type_const.output diff --git a/doc/examples/at_json_pointer.cpp b/docs/examples/at_json_pointer.cpp similarity index 100% rename from doc/examples/at_json_pointer.cpp rename to docs/examples/at_json_pointer.cpp diff --git a/doc/examples/at_json_pointer.output b/docs/examples/at_json_pointer.output similarity index 100% rename from doc/examples/at_json_pointer.output rename to docs/examples/at_json_pointer.output diff --git a/doc/examples/at_json_pointer_const.cpp b/docs/examples/at_json_pointer_const.cpp similarity index 100% rename from doc/examples/at_json_pointer_const.cpp rename to docs/examples/at_json_pointer_const.cpp diff --git a/doc/examples/at_json_pointer_const.output b/docs/examples/at_json_pointer_const.output similarity index 100% rename from doc/examples/at_json_pointer_const.output rename to docs/examples/at_json_pointer_const.output diff --git a/doc/examples/back.cpp b/docs/examples/back.cpp similarity index 100% rename from doc/examples/back.cpp rename to docs/examples/back.cpp diff --git a/doc/examples/back.output b/docs/examples/back.output similarity index 100% rename from doc/examples/back.output rename to docs/examples/back.output diff --git a/doc/examples/basic_json__CompatibleType.cpp b/docs/examples/basic_json__CompatibleType.cpp similarity index 100% rename from doc/examples/basic_json__CompatibleType.cpp rename to docs/examples/basic_json__CompatibleType.cpp diff --git a/doc/examples/basic_json__CompatibleType.output b/docs/examples/basic_json__CompatibleType.output similarity index 100% rename from doc/examples/basic_json__CompatibleType.output rename to docs/examples/basic_json__CompatibleType.output diff --git a/doc/examples/basic_json__InputIt_InputIt.cpp b/docs/examples/basic_json__InputIt_InputIt.cpp similarity index 100% rename from doc/examples/basic_json__InputIt_InputIt.cpp rename to docs/examples/basic_json__InputIt_InputIt.cpp diff --git a/doc/examples/basic_json__InputIt_InputIt.output b/docs/examples/basic_json__InputIt_InputIt.output similarity index 100% rename from doc/examples/basic_json__InputIt_InputIt.output rename to docs/examples/basic_json__InputIt_InputIt.output diff --git a/doc/examples/basic_json__basic_json.cpp b/docs/examples/basic_json__basic_json.cpp similarity index 100% rename from doc/examples/basic_json__basic_json.cpp rename to docs/examples/basic_json__basic_json.cpp diff --git a/doc/examples/basic_json__basic_json.output b/docs/examples/basic_json__basic_json.output similarity index 100% rename from doc/examples/basic_json__basic_json.output rename to docs/examples/basic_json__basic_json.output diff --git a/doc/examples/basic_json__copyassignment.cpp b/docs/examples/basic_json__copyassignment.cpp similarity index 100% rename from doc/examples/basic_json__copyassignment.cpp rename to docs/examples/basic_json__copyassignment.cpp diff --git a/doc/examples/basic_json__copyassignment.output b/docs/examples/basic_json__copyassignment.output similarity index 100% rename from doc/examples/basic_json__copyassignment.output rename to docs/examples/basic_json__copyassignment.output diff --git a/doc/examples/basic_json__list_init_t.cpp b/docs/examples/basic_json__list_init_t.cpp similarity index 100% rename from doc/examples/basic_json__list_init_t.cpp rename to docs/examples/basic_json__list_init_t.cpp diff --git a/doc/examples/basic_json__list_init_t.output b/docs/examples/basic_json__list_init_t.output similarity index 100% rename from doc/examples/basic_json__list_init_t.output rename to docs/examples/basic_json__list_init_t.output diff --git a/doc/examples/basic_json__moveconstructor.cpp b/docs/examples/basic_json__moveconstructor.cpp similarity index 100% rename from doc/examples/basic_json__moveconstructor.cpp rename to docs/examples/basic_json__moveconstructor.cpp diff --git a/doc/examples/basic_json__moveconstructor.output b/docs/examples/basic_json__moveconstructor.output similarity index 100% rename from doc/examples/basic_json__moveconstructor.output rename to docs/examples/basic_json__moveconstructor.output diff --git a/doc/examples/basic_json__nullptr_t.cpp b/docs/examples/basic_json__nullptr_t.cpp similarity index 100% rename from doc/examples/basic_json__nullptr_t.cpp rename to docs/examples/basic_json__nullptr_t.cpp diff --git a/doc/examples/basic_json__nullptr_t.output b/docs/examples/basic_json__nullptr_t.output similarity index 100% rename from doc/examples/basic_json__nullptr_t.output rename to docs/examples/basic_json__nullptr_t.output diff --git a/doc/examples/basic_json__size_type_basic_json.cpp b/docs/examples/basic_json__size_type_basic_json.cpp similarity index 100% rename from doc/examples/basic_json__size_type_basic_json.cpp rename to docs/examples/basic_json__size_type_basic_json.cpp diff --git a/doc/examples/basic_json__size_type_basic_json.output b/docs/examples/basic_json__size_type_basic_json.output similarity index 100% rename from doc/examples/basic_json__size_type_basic_json.output rename to docs/examples/basic_json__size_type_basic_json.output diff --git a/doc/examples/basic_json__value.cpp b/docs/examples/basic_json__value.cpp similarity index 100% rename from doc/examples/basic_json__value.cpp rename to docs/examples/basic_json__value.cpp diff --git a/doc/examples/basic_json__value.output b/docs/examples/basic_json__value.output similarity index 100% rename from doc/examples/basic_json__value.output rename to docs/examples/basic_json__value.output diff --git a/doc/examples/basic_json__value_ptr.cpp b/docs/examples/basic_json__value_ptr.cpp similarity index 100% rename from doc/examples/basic_json__value_ptr.cpp rename to docs/examples/basic_json__value_ptr.cpp diff --git a/doc/examples/basic_json__value_ptr.output b/docs/examples/basic_json__value_ptr.output similarity index 100% rename from doc/examples/basic_json__value_ptr.output rename to docs/examples/basic_json__value_ptr.output diff --git a/doc/examples/basic_json__value_t.cpp b/docs/examples/basic_json__value_t.cpp similarity index 100% rename from doc/examples/basic_json__value_t.cpp rename to docs/examples/basic_json__value_t.cpp diff --git a/doc/examples/basic_json__value_t.output b/docs/examples/basic_json__value_t.output similarity index 100% rename from doc/examples/basic_json__value_t.output rename to docs/examples/basic_json__value_t.output diff --git a/doc/examples/begin.cpp b/docs/examples/begin.cpp similarity index 100% rename from doc/examples/begin.cpp rename to docs/examples/begin.cpp diff --git a/doc/examples/begin.output b/docs/examples/begin.output similarity index 100% rename from doc/examples/begin.output rename to docs/examples/begin.output diff --git a/doc/examples/binary.cpp b/docs/examples/binary.cpp similarity index 100% rename from doc/examples/binary.cpp rename to docs/examples/binary.cpp diff --git a/doc/examples/binary.output b/docs/examples/binary.output similarity index 100% rename from doc/examples/binary.output rename to docs/examples/binary.output diff --git a/doc/examples/binary_t.cpp b/docs/examples/binary_t.cpp similarity index 100% rename from doc/examples/binary_t.cpp rename to docs/examples/binary_t.cpp diff --git a/doc/examples/binary_t.output b/docs/examples/binary_t.output similarity index 100% rename from doc/examples/binary_t.output rename to docs/examples/binary_t.output diff --git a/doc/examples/boolean_t.cpp b/docs/examples/boolean_t.cpp similarity index 100% rename from doc/examples/boolean_t.cpp rename to docs/examples/boolean_t.cpp diff --git a/doc/examples/boolean_t.output b/docs/examples/boolean_t.output similarity index 100% rename from doc/examples/boolean_t.output rename to docs/examples/boolean_t.output diff --git a/docs/examples/byte_container_with_subtype__byte_container_with_subtype.cpp b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.cpp new file mode 100644 index 000000000..1c10be5c2 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.cpp @@ -0,0 +1,23 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +using json = nlohmann::json; + +int main() +{ + // (1) create empty container + auto c1 = byte_container_with_subtype(); + + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // (2) create container + auto c2 = byte_container_with_subtype(bytes); + + // (3) create container with subtype + auto c3 = byte_container_with_subtype(bytes, 42); + + std::cout << json(c1) << "\n" << json(c2) << "\n" << json(c3) << std::endl; +} diff --git a/docs/examples/byte_container_with_subtype__byte_container_with_subtype.output b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.output new file mode 100644 index 000000000..67ac1b2ef --- /dev/null +++ b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.output @@ -0,0 +1,3 @@ +{"bytes":[],"subtype":null} +{"bytes":[202,254,186,190],"subtype":null} +{"bytes":[202,254,186,190],"subtype":42} diff --git a/docs/examples/byte_container_with_subtype__clear_subtype.cpp b/docs/examples/byte_container_with_subtype__clear_subtype.cpp new file mode 100644 index 000000000..f9ce6842b --- /dev/null +++ b/docs/examples/byte_container_with_subtype__clear_subtype.cpp @@ -0,0 +1,21 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +using json = nlohmann::json; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container with subtype + auto c1 = byte_container_with_subtype(bytes, 42); + + std::cout << "before calling clear_subtype(): " << json(c1) << '\n'; + + c1.clear_subtype(); + + std::cout << "after calling clear_subtype(): " << json(c1) << '\n'; +} diff --git a/docs/examples/byte_container_with_subtype__clear_subtype.output b/docs/examples/byte_container_with_subtype__clear_subtype.output new file mode 100644 index 000000000..9d8212946 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__clear_subtype.output @@ -0,0 +1,2 @@ +before calling clear_subtype(): {"bytes":[202,254,186,190],"subtype":42} +after calling clear_subtype(): {"bytes":[202,254,186,190],"subtype":null} diff --git a/docs/examples/byte_container_with_subtype__has_subtype.cpp b/docs/examples/byte_container_with_subtype__has_subtype.cpp new file mode 100644 index 000000000..61c21eaae --- /dev/null +++ b/docs/examples/byte_container_with_subtype__has_subtype.cpp @@ -0,0 +1,19 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container + auto c1 = byte_container_with_subtype(bytes); + + // create container with subtype + auto c2 = byte_container_with_subtype(bytes, 42); + + std::cout << std::boolalpha << "c1.has_subtype() = " << c1.has_subtype() + << "\nc2.has_subtype() = " << c2.has_subtype() << std::endl; +} diff --git a/docs/examples/byte_container_with_subtype__has_subtype.output b/docs/examples/byte_container_with_subtype__has_subtype.output new file mode 100644 index 000000000..f4aade2a1 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__has_subtype.output @@ -0,0 +1,2 @@ +c1.has_subtype() = false +c2.has_subtype() = true diff --git a/docs/examples/byte_container_with_subtype__set_subtype.cpp b/docs/examples/byte_container_with_subtype__set_subtype.cpp new file mode 100644 index 000000000..b2694c54d --- /dev/null +++ b/docs/examples/byte_container_with_subtype__set_subtype.cpp @@ -0,0 +1,22 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +using json = nlohmann::json; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container without subtype + auto c = byte_container_with_subtype(bytes); + + std::cout << "before calling set_subtype(42): " << json(c) << '\n'; + + // set the subtype + c.set_subtype(42); + + std::cout << "after calling set_subtype(42): " << json(c) << '\n'; +} diff --git a/docs/examples/byte_container_with_subtype__set_subtype.output b/docs/examples/byte_container_with_subtype__set_subtype.output new file mode 100644 index 000000000..648b3ef24 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__set_subtype.output @@ -0,0 +1,2 @@ +before calling set_subtype(42): {"bytes":[202,254,186,190],"subtype":null} +after calling set_subtype(42): {"bytes":[202,254,186,190],"subtype":42} diff --git a/docs/examples/byte_container_with_subtype__subtype.cpp b/docs/examples/byte_container_with_subtype__subtype.cpp new file mode 100644 index 000000000..cd230ade1 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__subtype.cpp @@ -0,0 +1,22 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container + auto c1 = byte_container_with_subtype(bytes); + + // create container with subtype + auto c2 = byte_container_with_subtype(bytes, 42); + + std::cout << "c1.subtype() = " << c1.subtype() + << "\nc2.subtype() = " << c2.subtype() << std::endl; + + // in case no subtype is set, return special value + assert(c1.subtype() == static_cast(-1)); +} diff --git a/docs/examples/byte_container_with_subtype__subtype.output b/docs/examples/byte_container_with_subtype__subtype.output new file mode 100644 index 000000000..47955277b --- /dev/null +++ b/docs/examples/byte_container_with_subtype__subtype.output @@ -0,0 +1,2 @@ +c1.subtype() = 18446744073709551615 +c2.subtype() = 42 diff --git a/doc/examples/cbegin.cpp b/docs/examples/cbegin.cpp similarity index 100% rename from doc/examples/cbegin.cpp rename to docs/examples/cbegin.cpp diff --git a/doc/examples/cbegin.output b/docs/examples/cbegin.output similarity index 100% rename from doc/examples/cbegin.output rename to docs/examples/cbegin.output diff --git a/docs/examples/cbor_tag_handler_t.cpp b/docs/examples/cbor_tag_handler_t.cpp new file mode 100644 index 000000000..79052c7a0 --- /dev/null +++ b/docs/examples/cbor_tag_handler_t.cpp @@ -0,0 +1,28 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // tagged byte string + std::vector vec = {{0xd8, 0x42, 0x44, 0xcA, 0xfe, 0xba, 0xbe}}; + + // cbor_tag_handler_t::error throws + try + { + auto b_throw_on_tag = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::error); + } + catch (json::parse_error& e) + { + std::cout << e.what() << std::endl; + } + + // cbor_tag_handler_t::ignore ignores the tag + auto b_ignore_tag = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::ignore); + std::cout << b_ignore_tag << std::endl; + + // cbor_tag_handler_t::store stores the tag as binary subtype + auto b_store_tag = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::store); + std::cout << b_store_tag << std::endl; +} diff --git a/docs/examples/cbor_tag_handler_t.output b/docs/examples/cbor_tag_handler_t.output new file mode 100644 index 000000000..18920b137 --- /dev/null +++ b/docs/examples/cbor_tag_handler_t.output @@ -0,0 +1,3 @@ +[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0xD8 +{"bytes":[202,254,186,190],"subtype":null} +{"bytes":[202,254,186,190],"subtype":66} diff --git a/doc/examples/cend.cpp b/docs/examples/cend.cpp similarity index 100% rename from doc/examples/cend.cpp rename to docs/examples/cend.cpp diff --git a/doc/examples/cend.output b/docs/examples/cend.output similarity index 100% rename from doc/examples/cend.output rename to docs/examples/cend.output diff --git a/doc/examples/clear.cpp b/docs/examples/clear.cpp similarity index 100% rename from doc/examples/clear.cpp rename to docs/examples/clear.cpp diff --git a/doc/examples/clear.output b/docs/examples/clear.output similarity index 100% rename from doc/examples/clear.output rename to docs/examples/clear.output diff --git a/doc/examples/contains.cpp b/docs/examples/contains.cpp similarity index 100% rename from doc/examples/contains.cpp rename to docs/examples/contains.cpp diff --git a/doc/examples/contains.output b/docs/examples/contains.output similarity index 100% rename from doc/examples/contains.output rename to docs/examples/contains.output diff --git a/doc/examples/contains_json_pointer.cpp b/docs/examples/contains_json_pointer.cpp similarity index 100% rename from doc/examples/contains_json_pointer.cpp rename to docs/examples/contains_json_pointer.cpp diff --git a/doc/examples/contains_json_pointer.output b/docs/examples/contains_json_pointer.output similarity index 100% rename from doc/examples/contains_json_pointer.output rename to docs/examples/contains_json_pointer.output diff --git a/doc/examples/count.cpp b/docs/examples/count.cpp similarity index 100% rename from doc/examples/count.cpp rename to docs/examples/count.cpp diff --git a/doc/examples/count.output b/docs/examples/count.output similarity index 100% rename from doc/examples/count.output rename to docs/examples/count.output diff --git a/doc/examples/crbegin.cpp b/docs/examples/crbegin.cpp similarity index 100% rename from doc/examples/crbegin.cpp rename to docs/examples/crbegin.cpp diff --git a/doc/examples/crbegin.output b/docs/examples/crbegin.output similarity index 100% rename from doc/examples/crbegin.output rename to docs/examples/crbegin.output diff --git a/doc/examples/crend.cpp b/docs/examples/crend.cpp similarity index 100% rename from doc/examples/crend.cpp rename to docs/examples/crend.cpp diff --git a/doc/examples/crend.output b/docs/examples/crend.output similarity index 100% rename from doc/examples/crend.output rename to docs/examples/crend.output diff --git a/docs/examples/default_object_comparator_t.cpp b/docs/examples/default_object_comparator_t.cpp new file mode 100644 index 000000000..9f200fe6b --- /dev/null +++ b/docs/examples/default_object_comparator_t.cpp @@ -0,0 +1,11 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::boolalpha + << "one < two : " << json::default_object_comparator_t{}("one", "two") << "\n" + << "three < four : " << json::default_object_comparator_t{}("three", "four") << std::endl; +} diff --git a/docs/examples/default_object_comparator_t.output b/docs/examples/default_object_comparator_t.output new file mode 100644 index 000000000..b1daf3b96 --- /dev/null +++ b/docs/examples/default_object_comparator_t.output @@ -0,0 +1,2 @@ +one < two : true +three < four : false diff --git a/doc/examples/diagnostics_extended.cpp b/docs/examples/diagnostics_extended.cpp similarity index 100% rename from doc/examples/diagnostics_extended.cpp rename to docs/examples/diagnostics_extended.cpp diff --git a/doc/examples/diagnostics_extended.output b/docs/examples/diagnostics_extended.output similarity index 100% rename from doc/examples/diagnostics_extended.output rename to docs/examples/diagnostics_extended.output diff --git a/doc/examples/diagnostics_standard.cpp b/docs/examples/diagnostics_standard.cpp similarity index 100% rename from doc/examples/diagnostics_standard.cpp rename to docs/examples/diagnostics_standard.cpp diff --git a/doc/examples/diagnostics_standard.output b/docs/examples/diagnostics_standard.output similarity index 100% rename from doc/examples/diagnostics_standard.output rename to docs/examples/diagnostics_standard.output diff --git a/doc/examples/diff.cpp b/docs/examples/diff.cpp similarity index 100% rename from doc/examples/diff.cpp rename to docs/examples/diff.cpp diff --git a/doc/examples/diff.output b/docs/examples/diff.output similarity index 100% rename from doc/examples/diff.output rename to docs/examples/diff.output diff --git a/doc/examples/dump.cpp b/docs/examples/dump.cpp similarity index 100% rename from doc/examples/dump.cpp rename to docs/examples/dump.cpp diff --git a/doc/examples/dump.output b/docs/examples/dump.output similarity index 100% rename from doc/examples/dump.output rename to docs/examples/dump.output diff --git a/doc/examples/emplace.cpp b/docs/examples/emplace.cpp similarity index 100% rename from doc/examples/emplace.cpp rename to docs/examples/emplace.cpp diff --git a/doc/examples/emplace.output b/docs/examples/emplace.output similarity index 100% rename from doc/examples/emplace.output rename to docs/examples/emplace.output diff --git a/doc/examples/emplace_back.cpp b/docs/examples/emplace_back.cpp similarity index 100% rename from doc/examples/emplace_back.cpp rename to docs/examples/emplace_back.cpp diff --git a/doc/examples/emplace_back.output b/docs/examples/emplace_back.output similarity index 100% rename from doc/examples/emplace_back.output rename to docs/examples/emplace_back.output diff --git a/doc/examples/empty.cpp b/docs/examples/empty.cpp similarity index 100% rename from doc/examples/empty.cpp rename to docs/examples/empty.cpp diff --git a/doc/examples/empty.output b/docs/examples/empty.output similarity index 100% rename from doc/examples/empty.output rename to docs/examples/empty.output diff --git a/doc/examples/end.cpp b/docs/examples/end.cpp similarity index 100% rename from doc/examples/end.cpp rename to docs/examples/end.cpp diff --git a/doc/examples/end.output b/docs/examples/end.output similarity index 100% rename from doc/examples/end.output rename to docs/examples/end.output diff --git a/doc/examples/erase__IteratorType.cpp b/docs/examples/erase__IteratorType.cpp similarity index 100% rename from doc/examples/erase__IteratorType.cpp rename to docs/examples/erase__IteratorType.cpp diff --git a/doc/examples/erase__IteratorType.output b/docs/examples/erase__IteratorType.output similarity index 100% rename from doc/examples/erase__IteratorType.output rename to docs/examples/erase__IteratorType.output diff --git a/doc/examples/erase__IteratorType_IteratorType.cpp b/docs/examples/erase__IteratorType_IteratorType.cpp similarity index 100% rename from doc/examples/erase__IteratorType_IteratorType.cpp rename to docs/examples/erase__IteratorType_IteratorType.cpp diff --git a/doc/examples/erase__IteratorType_IteratorType.output b/docs/examples/erase__IteratorType_IteratorType.output similarity index 100% rename from doc/examples/erase__IteratorType_IteratorType.output rename to docs/examples/erase__IteratorType_IteratorType.output diff --git a/doc/examples/erase__key_type.cpp b/docs/examples/erase__key_type.cpp similarity index 100% rename from doc/examples/erase__key_type.cpp rename to docs/examples/erase__key_type.cpp diff --git a/doc/examples/erase__key_type.output b/docs/examples/erase__key_type.output similarity index 100% rename from doc/examples/erase__key_type.output rename to docs/examples/erase__key_type.output diff --git a/doc/examples/erase__size_type.cpp b/docs/examples/erase__size_type.cpp similarity index 100% rename from doc/examples/erase__size_type.cpp rename to docs/examples/erase__size_type.cpp diff --git a/doc/examples/erase__size_type.output b/docs/examples/erase__size_type.output similarity index 100% rename from doc/examples/erase__size_type.output rename to docs/examples/erase__size_type.output diff --git a/docs/examples/error_handler_t.cpp b/docs/examples/error_handler_t.cpp new file mode 100644 index 000000000..add3f3b2d --- /dev/null +++ b/docs/examples/error_handler_t.cpp @@ -0,0 +1,24 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create JSON value with invalid UTF-8 byte sequence + json j_invalid = "ä\xA9ü"; + try + { + std::cout << j_invalid.dump() << std::endl; + } + catch (json::type_error& e) + { + std::cout << e.what() << std::endl; + } + + std::cout << "string with replaced invalid characters: " + << j_invalid.dump(-1, ' ', false, json::error_handler_t::replace) + << "\nstring with ignored invalid characters: " + << j_invalid.dump(-1, ' ', false, json::error_handler_t::ignore) + << '\n'; +} diff --git a/docs/examples/error_handler_t.output b/docs/examples/error_handler_t.output new file mode 100644 index 000000000..718d62bee --- /dev/null +++ b/docs/examples/error_handler_t.output @@ -0,0 +1,3 @@ +[json.exception.type_error.316] invalid UTF-8 byte at index 2: 0xA9 +string with replaced invalid characters: "ä�ü" +string with ignored invalid characters: "äü" diff --git a/doc/examples/exception.cpp b/docs/examples/exception.cpp similarity index 100% rename from doc/examples/exception.cpp rename to docs/examples/exception.cpp diff --git a/doc/examples/exception.output b/docs/examples/exception.output similarity index 100% rename from doc/examples/exception.output rename to docs/examples/exception.output diff --git a/doc/examples/find__key_type.cpp b/docs/examples/find__key_type.cpp similarity index 100% rename from doc/examples/find__key_type.cpp rename to docs/examples/find__key_type.cpp diff --git a/doc/examples/find__key_type.output b/docs/examples/find__key_type.output similarity index 100% rename from doc/examples/find__key_type.output rename to docs/examples/find__key_type.output diff --git a/doc/examples/flatten.cpp b/docs/examples/flatten.cpp similarity index 100% rename from doc/examples/flatten.cpp rename to docs/examples/flatten.cpp diff --git a/doc/examples/flatten.output b/docs/examples/flatten.output similarity index 100% rename from doc/examples/flatten.output rename to docs/examples/flatten.output diff --git a/docs/examples/from_bjdata.cpp b/docs/examples/from_bjdata.cpp new file mode 100644 index 000000000..961164c29 --- /dev/null +++ b/docs/examples/from_bjdata.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create byte vector + std::vector v = {0x7B, 0x69, 0x07, 0x63, 0x6F, 0x6D, 0x70, 0x61, + 0x63, 0x74, 0x54, 0x69, 0x06, 0x73, 0x63, 0x68, + 0x65, 0x6D, 0x61, 0x69, 0x00, 0x7D + }; + + // deserialize it with BJData + json j = json::from_bjdata(v); + + // print the deserialized JSON value + std::cout << std::setw(2) << j << std::endl; +} diff --git a/doc/examples/from_bson.output b/docs/examples/from_bjdata.output similarity index 100% rename from doc/examples/from_bson.output rename to docs/examples/from_bjdata.output diff --git a/doc/examples/from_bson.cpp b/docs/examples/from_bson.cpp similarity index 100% rename from doc/examples/from_bson.cpp rename to docs/examples/from_bson.cpp diff --git a/doc/examples/from_cbor.output b/docs/examples/from_bson.output similarity index 100% rename from doc/examples/from_cbor.output rename to docs/examples/from_bson.output diff --git a/doc/examples/from_cbor.cpp b/docs/examples/from_cbor.cpp similarity index 100% rename from doc/examples/from_cbor.cpp rename to docs/examples/from_cbor.cpp diff --git a/doc/examples/from_msgpack.output b/docs/examples/from_cbor.output similarity index 100% rename from doc/examples/from_msgpack.output rename to docs/examples/from_cbor.output diff --git a/doc/examples/from_msgpack.cpp b/docs/examples/from_msgpack.cpp similarity index 100% rename from doc/examples/from_msgpack.cpp rename to docs/examples/from_msgpack.cpp diff --git a/doc/examples/from_ubjson.output b/docs/examples/from_msgpack.output similarity index 100% rename from doc/examples/from_ubjson.output rename to docs/examples/from_msgpack.output diff --git a/doc/examples/from_ubjson.cpp b/docs/examples/from_ubjson.cpp similarity index 100% rename from doc/examples/from_ubjson.cpp rename to docs/examples/from_ubjson.cpp diff --git a/docs/examples/from_ubjson.output b/docs/examples/from_ubjson.output new file mode 100644 index 000000000..259f63bd4 --- /dev/null +++ b/docs/examples/from_ubjson.output @@ -0,0 +1,4 @@ +{ + "compact": true, + "schema": 0 +} diff --git a/doc/examples/front.cpp b/docs/examples/front.cpp similarity index 100% rename from doc/examples/front.cpp rename to docs/examples/front.cpp diff --git a/doc/examples/front.output b/docs/examples/front.output similarity index 100% rename from doc/examples/front.output rename to docs/examples/front.output diff --git a/doc/examples/get__PointerType.cpp b/docs/examples/get__PointerType.cpp similarity index 100% rename from doc/examples/get__PointerType.cpp rename to docs/examples/get__PointerType.cpp diff --git a/doc/examples/get__PointerType.output b/docs/examples/get__PointerType.output similarity index 100% rename from doc/examples/get__PointerType.output rename to docs/examples/get__PointerType.output diff --git a/doc/examples/get__ValueType_const.cpp b/docs/examples/get__ValueType_const.cpp similarity index 100% rename from doc/examples/get__ValueType_const.cpp rename to docs/examples/get__ValueType_const.cpp diff --git a/doc/examples/get__ValueType_const.output b/docs/examples/get__ValueType_const.output similarity index 100% rename from doc/examples/get__ValueType_const.output rename to docs/examples/get__ValueType_const.output diff --git a/docs/examples/get_allocator.cpp b/docs/examples/get_allocator.cpp new file mode 100644 index 000000000..35079a10c --- /dev/null +++ b/docs/examples/get_allocator.cpp @@ -0,0 +1,18 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + auto alloc = json::get_allocator(); + using traits_t = std::allocator_traits; + + json* j = traits_t::allocate(alloc, 1); + traits_t::construct(alloc, j, "Hello, world!"); + + std::cout << *j << std::endl; + + traits_t::destroy(alloc, j); + traits_t::deallocate(alloc, j, 1); +} diff --git a/docs/examples/get_allocator.output b/docs/examples/get_allocator.output new file mode 100644 index 000000000..8effb3e8c --- /dev/null +++ b/docs/examples/get_allocator.output @@ -0,0 +1 @@ +"Hello, world!" diff --git a/doc/examples/get_binary.cpp b/docs/examples/get_binary.cpp similarity index 100% rename from doc/examples/get_binary.cpp rename to docs/examples/get_binary.cpp diff --git a/doc/examples/get_binary.output b/docs/examples/get_binary.output similarity index 100% rename from doc/examples/get_binary.output rename to docs/examples/get_binary.output diff --git a/doc/examples/get_ptr.cpp b/docs/examples/get_ptr.cpp similarity index 100% rename from doc/examples/get_ptr.cpp rename to docs/examples/get_ptr.cpp diff --git a/doc/examples/get_ptr.output b/docs/examples/get_ptr.output similarity index 100% rename from doc/examples/get_ptr.output rename to docs/examples/get_ptr.output diff --git a/doc/examples/get_ref.cpp b/docs/examples/get_ref.cpp similarity index 100% rename from doc/examples/get_ref.cpp rename to docs/examples/get_ref.cpp diff --git a/doc/examples/get_ref.output b/docs/examples/get_ref.output similarity index 100% rename from doc/examples/get_ref.output rename to docs/examples/get_ref.output diff --git a/doc/examples/get_to.cpp b/docs/examples/get_to.cpp similarity index 100% rename from doc/examples/get_to.cpp rename to docs/examples/get_to.cpp diff --git a/doc/examples/get_to.output b/docs/examples/get_to.output similarity index 100% rename from doc/examples/get_to.output rename to docs/examples/get_to.output diff --git a/doc/examples/insert.cpp b/docs/examples/insert.cpp similarity index 100% rename from doc/examples/insert.cpp rename to docs/examples/insert.cpp diff --git a/doc/examples/insert.output b/docs/examples/insert.output similarity index 100% rename from doc/examples/insert.output rename to docs/examples/insert.output diff --git a/doc/examples/insert__count.cpp b/docs/examples/insert__count.cpp similarity index 100% rename from doc/examples/insert__count.cpp rename to docs/examples/insert__count.cpp diff --git a/doc/examples/insert__count.output b/docs/examples/insert__count.output similarity index 100% rename from doc/examples/insert__count.output rename to docs/examples/insert__count.output diff --git a/doc/examples/insert__ilist.cpp b/docs/examples/insert__ilist.cpp similarity index 100% rename from doc/examples/insert__ilist.cpp rename to docs/examples/insert__ilist.cpp diff --git a/doc/examples/insert__ilist.output b/docs/examples/insert__ilist.output similarity index 100% rename from doc/examples/insert__ilist.output rename to docs/examples/insert__ilist.output diff --git a/doc/examples/insert__range.cpp b/docs/examples/insert__range.cpp similarity index 100% rename from doc/examples/insert__range.cpp rename to docs/examples/insert__range.cpp diff --git a/doc/examples/insert__range.output b/docs/examples/insert__range.output similarity index 100% rename from doc/examples/insert__range.output rename to docs/examples/insert__range.output diff --git a/doc/examples/insert__range_object.cpp b/docs/examples/insert__range_object.cpp similarity index 100% rename from doc/examples/insert__range_object.cpp rename to docs/examples/insert__range_object.cpp diff --git a/doc/examples/insert__range_object.output b/docs/examples/insert__range_object.output similarity index 100% rename from doc/examples/insert__range_object.output rename to docs/examples/insert__range_object.output diff --git a/doc/examples/invalid_iterator.cpp b/docs/examples/invalid_iterator.cpp similarity index 100% rename from doc/examples/invalid_iterator.cpp rename to docs/examples/invalid_iterator.cpp diff --git a/doc/examples/invalid_iterator.output b/docs/examples/invalid_iterator.output similarity index 100% rename from doc/examples/invalid_iterator.output rename to docs/examples/invalid_iterator.output diff --git a/doc/examples/is_array.cpp b/docs/examples/is_array.cpp similarity index 100% rename from doc/examples/is_array.cpp rename to docs/examples/is_array.cpp diff --git a/doc/examples/is_array.output b/docs/examples/is_array.output similarity index 100% rename from doc/examples/is_array.output rename to docs/examples/is_array.output diff --git a/doc/examples/is_binary.cpp b/docs/examples/is_binary.cpp similarity index 100% rename from doc/examples/is_binary.cpp rename to docs/examples/is_binary.cpp diff --git a/doc/examples/is_binary.output b/docs/examples/is_binary.output similarity index 100% rename from doc/examples/is_binary.output rename to docs/examples/is_binary.output diff --git a/doc/examples/is_boolean.cpp b/docs/examples/is_boolean.cpp similarity index 100% rename from doc/examples/is_boolean.cpp rename to docs/examples/is_boolean.cpp diff --git a/doc/examples/is_boolean.output b/docs/examples/is_boolean.output similarity index 100% rename from doc/examples/is_boolean.output rename to docs/examples/is_boolean.output diff --git a/doc/examples/is_discarded.cpp b/docs/examples/is_discarded.cpp similarity index 100% rename from doc/examples/is_discarded.cpp rename to docs/examples/is_discarded.cpp diff --git a/doc/examples/is_discarded.output b/docs/examples/is_discarded.output similarity index 100% rename from doc/examples/is_discarded.output rename to docs/examples/is_discarded.output diff --git a/doc/examples/is_null.cpp b/docs/examples/is_null.cpp similarity index 100% rename from doc/examples/is_null.cpp rename to docs/examples/is_null.cpp diff --git a/doc/examples/is_null.output b/docs/examples/is_null.output similarity index 100% rename from doc/examples/is_null.output rename to docs/examples/is_null.output diff --git a/doc/examples/is_number.cpp b/docs/examples/is_number.cpp similarity index 100% rename from doc/examples/is_number.cpp rename to docs/examples/is_number.cpp diff --git a/doc/examples/is_number.output b/docs/examples/is_number.output similarity index 100% rename from doc/examples/is_number.output rename to docs/examples/is_number.output diff --git a/doc/examples/is_number_float.cpp b/docs/examples/is_number_float.cpp similarity index 100% rename from doc/examples/is_number_float.cpp rename to docs/examples/is_number_float.cpp diff --git a/doc/examples/is_number_float.output b/docs/examples/is_number_float.output similarity index 100% rename from doc/examples/is_number_float.output rename to docs/examples/is_number_float.output diff --git a/doc/examples/is_number_integer.cpp b/docs/examples/is_number_integer.cpp similarity index 100% rename from doc/examples/is_number_integer.cpp rename to docs/examples/is_number_integer.cpp diff --git a/doc/examples/is_number_integer.output b/docs/examples/is_number_integer.output similarity index 100% rename from doc/examples/is_number_integer.output rename to docs/examples/is_number_integer.output diff --git a/doc/examples/is_number_unsigned.cpp b/docs/examples/is_number_unsigned.cpp similarity index 100% rename from doc/examples/is_number_unsigned.cpp rename to docs/examples/is_number_unsigned.cpp diff --git a/doc/examples/is_number_unsigned.output b/docs/examples/is_number_unsigned.output similarity index 100% rename from doc/examples/is_number_unsigned.output rename to docs/examples/is_number_unsigned.output diff --git a/doc/examples/is_object.cpp b/docs/examples/is_object.cpp similarity index 100% rename from doc/examples/is_object.cpp rename to docs/examples/is_object.cpp diff --git a/doc/examples/is_object.output b/docs/examples/is_object.output similarity index 100% rename from doc/examples/is_object.output rename to docs/examples/is_object.output diff --git a/doc/examples/is_primitive.cpp b/docs/examples/is_primitive.cpp similarity index 100% rename from doc/examples/is_primitive.cpp rename to docs/examples/is_primitive.cpp diff --git a/doc/examples/is_primitive.output b/docs/examples/is_primitive.output similarity index 100% rename from doc/examples/is_primitive.output rename to docs/examples/is_primitive.output diff --git a/doc/examples/is_string.cpp b/docs/examples/is_string.cpp similarity index 100% rename from doc/examples/is_string.cpp rename to docs/examples/is_string.cpp diff --git a/doc/examples/is_string.output b/docs/examples/is_string.output similarity index 100% rename from doc/examples/is_string.output rename to docs/examples/is_string.output diff --git a/doc/examples/is_structured.cpp b/docs/examples/is_structured.cpp similarity index 100% rename from doc/examples/is_structured.cpp rename to docs/examples/is_structured.cpp diff --git a/doc/examples/is_structured.output b/docs/examples/is_structured.output similarity index 100% rename from doc/examples/is_structured.output rename to docs/examples/is_structured.output diff --git a/doc/examples/items.cpp b/docs/examples/items.cpp similarity index 100% rename from doc/examples/items.cpp rename to docs/examples/items.cpp diff --git a/doc/examples/items.output b/docs/examples/items.output similarity index 100% rename from doc/examples/items.output rename to docs/examples/items.output diff --git a/doc/examples/json_lines.cpp b/docs/examples/json_lines.cpp similarity index 100% rename from doc/examples/json_lines.cpp rename to docs/examples/json_lines.cpp diff --git a/doc/examples/json_lines.output b/docs/examples/json_lines.output similarity index 100% rename from doc/examples/json_lines.output rename to docs/examples/json_lines.output diff --git a/doc/examples/json_pointer.cpp b/docs/examples/json_pointer.cpp similarity index 100% rename from doc/examples/json_pointer.cpp rename to docs/examples/json_pointer.cpp diff --git a/doc/examples/json_pointer.output b/docs/examples/json_pointer.output similarity index 100% rename from doc/examples/json_pointer.output rename to docs/examples/json_pointer.output diff --git a/doc/examples/json_pointer__back.cpp b/docs/examples/json_pointer__back.cpp similarity index 100% rename from doc/examples/json_pointer__back.cpp rename to docs/examples/json_pointer__back.cpp diff --git a/doc/examples/json_pointer__back.output b/docs/examples/json_pointer__back.output similarity index 100% rename from doc/examples/json_pointer__back.output rename to docs/examples/json_pointer__back.output diff --git a/doc/examples/json_pointer__empty.cpp b/docs/examples/json_pointer__empty.cpp similarity index 100% rename from doc/examples/json_pointer__empty.cpp rename to docs/examples/json_pointer__empty.cpp diff --git a/doc/examples/json_pointer__empty.output b/docs/examples/json_pointer__empty.output similarity index 100% rename from doc/examples/json_pointer__empty.output rename to docs/examples/json_pointer__empty.output diff --git a/doc/examples/json_pointer__operator_add.cpp b/docs/examples/json_pointer__operator_add.cpp similarity index 100% rename from doc/examples/json_pointer__operator_add.cpp rename to docs/examples/json_pointer__operator_add.cpp diff --git a/doc/examples/json_pointer__operator_add.output b/docs/examples/json_pointer__operator_add.output similarity index 100% rename from doc/examples/json_pointer__operator_add.output rename to docs/examples/json_pointer__operator_add.output diff --git a/doc/examples/json_pointer__operator_add_binary.cpp b/docs/examples/json_pointer__operator_add_binary.cpp similarity index 100% rename from doc/examples/json_pointer__operator_add_binary.cpp rename to docs/examples/json_pointer__operator_add_binary.cpp diff --git a/doc/examples/json_pointer__operator_add_binary.output b/docs/examples/json_pointer__operator_add_binary.output similarity index 100% rename from doc/examples/json_pointer__operator_add_binary.output rename to docs/examples/json_pointer__operator_add_binary.output diff --git a/docs/examples/json_pointer__operator_string.cpp b/docs/examples/json_pointer__operator_string.cpp new file mode 100644 index 000000000..56f213020 --- /dev/null +++ b/docs/examples/json_pointer__operator_string.cpp @@ -0,0 +1,19 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON Pointers + json::json_pointer ptr1("/foo/0"); + json::json_pointer ptr2("/a~1b"); + + // implicit conversion to string + std::string s; + s += ptr1; + s += "\n"; + s += ptr2; + + std::cout << s << std::endl; +} diff --git a/docs/examples/json_pointer__operator_string.output b/docs/examples/json_pointer__operator_string.output new file mode 100644 index 000000000..ec6aba2c2 --- /dev/null +++ b/docs/examples/json_pointer__operator_string.output @@ -0,0 +1,2 @@ +/foo/0 +/a~1b diff --git a/doc/examples/json_pointer__parent_pointer.cpp b/docs/examples/json_pointer__parent_pointer.cpp similarity index 100% rename from doc/examples/json_pointer__parent_pointer.cpp rename to docs/examples/json_pointer__parent_pointer.cpp diff --git a/doc/examples/json_pointer__parent_pointer.output b/docs/examples/json_pointer__parent_pointer.output similarity index 100% rename from doc/examples/json_pointer__parent_pointer.output rename to docs/examples/json_pointer__parent_pointer.output diff --git a/doc/examples/json_pointer__pop_back.cpp b/docs/examples/json_pointer__pop_back.cpp similarity index 100% rename from doc/examples/json_pointer__pop_back.cpp rename to docs/examples/json_pointer__pop_back.cpp diff --git a/doc/examples/json_pointer__pop_back.output b/docs/examples/json_pointer__pop_back.output similarity index 100% rename from doc/examples/json_pointer__pop_back.output rename to docs/examples/json_pointer__pop_back.output diff --git a/doc/examples/json_pointer__push_back.cpp b/docs/examples/json_pointer__push_back.cpp similarity index 100% rename from doc/examples/json_pointer__push_back.cpp rename to docs/examples/json_pointer__push_back.cpp diff --git a/doc/examples/json_pointer__push_back.output b/docs/examples/json_pointer__push_back.output similarity index 100% rename from doc/examples/json_pointer__push_back.output rename to docs/examples/json_pointer__push_back.output diff --git a/docs/examples/json_pointer__string_t.cpp b/docs/examples/json_pointer__string_t.cpp new file mode 100644 index 000000000..fbe0f179e --- /dev/null +++ b/docs/examples/json_pointer__string_t.cpp @@ -0,0 +1,13 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + json::json_pointer::string_t s = "This is a string."; + + std::cout << s << std::endl; + + std::cout << std::boolalpha << std::is_same::value << std::endl; +} diff --git a/docs/examples/json_pointer__string_t.output b/docs/examples/json_pointer__string_t.output new file mode 100644 index 000000000..d87113724 --- /dev/null +++ b/docs/examples/json_pointer__string_t.output @@ -0,0 +1,2 @@ +This is a string. +true diff --git a/doc/examples/json_pointer__to_string.cpp b/docs/examples/json_pointer__to_string.cpp similarity index 99% rename from doc/examples/json_pointer__to_string.cpp rename to docs/examples/json_pointer__to_string.cpp index da397cdf4..ae1361aaa 100644 --- a/doc/examples/json_pointer__to_string.cpp +++ b/docs/examples/json_pointer__to_string.cpp @@ -19,7 +19,6 @@ int main() json::json_pointer ptr11("/ "); json::json_pointer ptr12("/m~0n"); - std::cout << ptr1.to_string() << '\n' << ptr2.to_string() << '\n' << ptr3.to_string() << '\n' diff --git a/doc/examples/json_pointer__to_string.output b/docs/examples/json_pointer__to_string.output similarity index 100% rename from doc/examples/json_pointer__to_string.output rename to docs/examples/json_pointer__to_string.output diff --git a/doc/examples/max_size.cpp b/docs/examples/max_size.cpp similarity index 100% rename from doc/examples/max_size.cpp rename to docs/examples/max_size.cpp diff --git a/doc/examples/max_size.output b/docs/examples/max_size.output similarity index 100% rename from doc/examples/max_size.output rename to docs/examples/max_size.output diff --git a/doc/examples/merge_patch.cpp b/docs/examples/merge_patch.cpp similarity index 100% rename from doc/examples/merge_patch.cpp rename to docs/examples/merge_patch.cpp diff --git a/doc/examples/merge_patch.output b/docs/examples/merge_patch.output similarity index 100% rename from doc/examples/merge_patch.output rename to docs/examples/merge_patch.output diff --git a/doc/examples/meta.cpp b/docs/examples/meta.cpp similarity index 100% rename from doc/examples/meta.cpp rename to docs/examples/meta.cpp diff --git a/doc/examples/meta.output b/docs/examples/meta.output similarity index 100% rename from doc/examples/meta.output rename to docs/examples/meta.output diff --git a/docs/examples/nlohmann_define_type_intrusive_explicit.cpp b/docs/examples/nlohmann_define_type_intrusive_explicit.cpp new file mode 100644 index 000000000..fb7701dec --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_explicit.cpp @@ -0,0 +1,59 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) + { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) + { + nlohmann_json_t.name = nlohmann_json_j.at("name"); + nlohmann_json_t.address = nlohmann_json_j.at("address"); + nlohmann_json_t.age = nlohmann_json_j.at("age"); + } +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_intrusive_explicit.output b/docs/examples/nlohmann_define_type_intrusive_explicit.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_intrusive_macro.cpp b/docs/examples/nlohmann_define_type_intrusive_macro.cpp new file mode 100644 index 000000000..ce292659a --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_macro.cpp @@ -0,0 +1,47 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(person, name, address, age) +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_intrusive_macro.output b/docs/examples/nlohmann_define_type_intrusive_macro.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp new file mode 100644 index 000000000..621ed1452 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp @@ -0,0 +1,54 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) + { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) + { + person nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address); + nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.age); + } +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.output b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp new file mode 100644 index 000000000..7851f526e --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp @@ -0,0 +1,41 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(person, name, address, age) +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_macro.output b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp b/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp new file mode 100644 index 000000000..b9d30dd8f --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp @@ -0,0 +1,52 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +struct person +{ + std::string name; + std::string address; + int age; +}; + +void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) +{ + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; +} + +void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) +{ + nlohmann_json_t.name = nlohmann_json_j.at("name"); + nlohmann_json_t.address = nlohmann_json_j.at("address"); + nlohmann_json_t.age = nlohmann_json_j.at("age"); +} +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_explicit.output b/docs/examples/nlohmann_define_type_non_intrusive_explicit.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp b/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp new file mode 100644 index 000000000..b073ef615 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp @@ -0,0 +1,40 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +struct person +{ + std::string name; + std::string address; + int age; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age) +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_macro.output b/docs/examples/nlohmann_define_type_non_intrusive_macro.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp new file mode 100644 index 000000000..21967b638 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp @@ -0,0 +1,52 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +struct person +{ + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} +}; + +void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) +{ + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; +} + +void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) +{ + person nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address); + nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.age); +} +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.output b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp new file mode 100644 index 000000000..470fed69c --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp @@ -0,0 +1,39 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +struct person +{ + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(person, name, address, age) +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.output b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_json_serialize_enum.cpp b/docs/examples/nlohmann_json_serialize_enum.cpp new file mode 100644 index 000000000..f9e472c64 --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum.cpp @@ -0,0 +1,59 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +enum TaskState +{ + TS_STOPPED, + TS_RUNNING, + TS_COMPLETED, + TS_INVALID = -1 +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, +{ + { TS_INVALID, nullptr }, + { TS_STOPPED, "stopped" }, + { TS_RUNNING, "running" }, + { TS_COMPLETED, "completed" } +}) + +enum class Color +{ + red, green, blue, unknown +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(Color, +{ + { Color::unknown, "unknown" }, { Color::red, "red" }, + { Color::green, "green" }, { Color::blue, "blue" } +}) +} // namespace ns + +int main() +{ + // serialization + json j_stopped = ns::TS_STOPPED; + json j_red = ns::Color::red; + std::cout << "ns::TS_STOPPED -> " << j_stopped + << ", ns::Color::red -> " << j_red << std::endl; + + // deserialization + json j_running = "running"; + json j_blue = "blue"; + auto running = j_running.get(); + auto blue = j_blue.get(); + std::cout << j_running << " -> " << running + << ", " << j_blue << " -> " << static_cast(blue) << std::endl; + + // deserializing undefined JSON value to enum + // (where the first map entry above is the default) + json j_pi = 3.14; + auto invalid = j_pi.get(); + auto unknown = j_pi.get(); + std::cout << j_pi << " -> " << invalid << ", " + << j_pi << " -> " << static_cast(unknown) << std::endl; +} diff --git a/docs/examples/nlohmann_json_serialize_enum.output b/docs/examples/nlohmann_json_serialize_enum.output new file mode 100644 index 000000000..f512563dd --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum.output @@ -0,0 +1,3 @@ +ns::TS_STOPPED -> "stopped", ns::Color::red -> "red" +"running" -> 1, "blue" -> 2 +3.14 -> -1, 3.14 -> 3 diff --git a/docs/examples/nlohmann_json_serialize_enum_2.cpp b/docs/examples/nlohmann_json_serialize_enum_2.cpp new file mode 100644 index 000000000..fd27226ca --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum_2.cpp @@ -0,0 +1,33 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +enum class Color +{ + red, green, blue, unknown +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(Color, +{ + { Color::unknown, "unknown" }, { Color::red, "red" }, + { Color::green, "green" }, { Color::blue, "blue" }, + { Color::red, "rot" } // a second conversion for Color::red +}) +} + +int main() +{ + // serialization + json j_red = ns::Color::red; + std::cout << static_cast(ns::Color::red) << " -> " << j_red << std::endl; + + // deserialization + json j_rot = "rot"; + auto rot = j_rot.get(); + auto red = j_red.get(); + std::cout << j_rot << " -> " << static_cast(rot) << std::endl; + std::cout << j_red << " -> " << static_cast(red) << std::endl; +} diff --git a/docs/examples/nlohmann_json_serialize_enum_2.output b/docs/examples/nlohmann_json_serialize_enum_2.output new file mode 100644 index 000000000..5dec31b4a --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum_2.output @@ -0,0 +1,3 @@ +0 -> "red" +"rot" -> 0 +"red" -> 0 diff --git a/docs/examples/nlohmann_json_version.cpp b/docs/examples/nlohmann_json_version.cpp new file mode 100644 index 000000000..ca5f53728 --- /dev/null +++ b/docs/examples/nlohmann_json_version.cpp @@ -0,0 +1,12 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << "JSON for Modern C++ version " + << NLOHMANN_JSON_VERSION_MAJOR << "." + << NLOHMANN_JSON_VERSION_MINOR << "." + << NLOHMANN_JSON_VERSION_PATCH << std::endl; +} diff --git a/docs/examples/nlohmann_json_version.output b/docs/examples/nlohmann_json_version.output new file mode 100644 index 000000000..600343999 --- /dev/null +++ b/docs/examples/nlohmann_json_version.output @@ -0,0 +1 @@ +JSON for Modern C++ version 3.10.5 diff --git a/doc/examples/number_float_t.cpp b/docs/examples/number_float_t.cpp similarity index 100% rename from doc/examples/number_float_t.cpp rename to docs/examples/number_float_t.cpp diff --git a/doc/examples/number_float_t.output b/docs/examples/number_float_t.output similarity index 100% rename from doc/examples/number_float_t.output rename to docs/examples/number_float_t.output diff --git a/doc/examples/number_integer_t.cpp b/docs/examples/number_integer_t.cpp similarity index 100% rename from doc/examples/number_integer_t.cpp rename to docs/examples/number_integer_t.cpp diff --git a/doc/examples/number_integer_t.output b/docs/examples/number_integer_t.output similarity index 100% rename from doc/examples/number_integer_t.output rename to docs/examples/number_integer_t.output diff --git a/doc/examples/number_unsigned_t.cpp b/docs/examples/number_unsigned_t.cpp similarity index 100% rename from doc/examples/number_unsigned_t.cpp rename to docs/examples/number_unsigned_t.cpp diff --git a/doc/examples/number_unsigned_t.output b/docs/examples/number_unsigned_t.output similarity index 100% rename from doc/examples/number_unsigned_t.output rename to docs/examples/number_unsigned_t.output diff --git a/doc/examples/object.cpp b/docs/examples/object.cpp similarity index 100% rename from doc/examples/object.cpp rename to docs/examples/object.cpp diff --git a/doc/examples/object.output b/docs/examples/object.output similarity index 100% rename from doc/examples/object.output rename to docs/examples/object.output diff --git a/docs/examples/object_comparator_t.cpp b/docs/examples/object_comparator_t.cpp new file mode 100644 index 000000000..6b82c7ca6 --- /dev/null +++ b/docs/examples/object_comparator_t.cpp @@ -0,0 +1,11 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::boolalpha + << "json::object_comparator_t(\"one\", \"two\") = " << json::object_comparator_t{}("one", "two") << "\n" + << "json::object_comparator_t(\"three\", \"four\") = " << json::object_comparator_t{}("three", "four") << std::endl; +} diff --git a/docs/examples/object_comparator_t.output b/docs/examples/object_comparator_t.output new file mode 100644 index 000000000..63620edb4 --- /dev/null +++ b/docs/examples/object_comparator_t.output @@ -0,0 +1,2 @@ +json::object_comparator_t("one", "two") = true +json::object_comparator_t("three", "four") = false diff --git a/doc/examples/object_t.cpp b/docs/examples/object_t.cpp similarity index 100% rename from doc/examples/object_t.cpp rename to docs/examples/object_t.cpp diff --git a/doc/examples/object_t.output b/docs/examples/object_t.output similarity index 100% rename from doc/examples/object_t.output rename to docs/examples/object_t.output diff --git a/doc/examples/operator__ValueType.cpp b/docs/examples/operator__ValueType.cpp similarity index 100% rename from doc/examples/operator__ValueType.cpp rename to docs/examples/operator__ValueType.cpp diff --git a/doc/examples/operator__ValueType.output b/docs/examples/operator__ValueType.output similarity index 100% rename from doc/examples/operator__ValueType.output rename to docs/examples/operator__ValueType.output diff --git a/doc/examples/operator__equal.cpp b/docs/examples/operator__equal.cpp similarity index 100% rename from doc/examples/operator__equal.cpp rename to docs/examples/operator__equal.cpp diff --git a/doc/examples/operator__equal.output b/docs/examples/operator__equal.output similarity index 100% rename from doc/examples/operator__equal.output rename to docs/examples/operator__equal.output diff --git a/doc/examples/operator__equal__nullptr_t.cpp b/docs/examples/operator__equal__nullptr_t.cpp similarity index 100% rename from doc/examples/operator__equal__nullptr_t.cpp rename to docs/examples/operator__equal__nullptr_t.cpp diff --git a/doc/examples/operator__equal__nullptr_t.output b/docs/examples/operator__equal__nullptr_t.output similarity index 100% rename from doc/examples/operator__equal__nullptr_t.output rename to docs/examples/operator__equal__nullptr_t.output diff --git a/doc/examples/operator__greater.cpp b/docs/examples/operator__greater.cpp similarity index 100% rename from doc/examples/operator__greater.cpp rename to docs/examples/operator__greater.cpp diff --git a/doc/examples/operator__greater.output b/docs/examples/operator__greater.output similarity index 100% rename from doc/examples/operator__greater.output rename to docs/examples/operator__greater.output diff --git a/doc/examples/operator__greaterequal.cpp b/docs/examples/operator__greaterequal.cpp similarity index 100% rename from doc/examples/operator__greaterequal.cpp rename to docs/examples/operator__greaterequal.cpp diff --git a/doc/examples/operator__greaterequal.output b/docs/examples/operator__greaterequal.output similarity index 100% rename from doc/examples/operator__greaterequal.output rename to docs/examples/operator__greaterequal.output diff --git a/doc/examples/operator__less.cpp b/docs/examples/operator__less.cpp similarity index 100% rename from doc/examples/operator__less.cpp rename to docs/examples/operator__less.cpp diff --git a/doc/examples/operator__less.output b/docs/examples/operator__less.output similarity index 100% rename from doc/examples/operator__less.output rename to docs/examples/operator__less.output diff --git a/doc/examples/operator__lessequal.cpp b/docs/examples/operator__lessequal.cpp similarity index 100% rename from doc/examples/operator__lessequal.cpp rename to docs/examples/operator__lessequal.cpp diff --git a/doc/examples/operator__lessequal.output b/docs/examples/operator__lessequal.output similarity index 100% rename from doc/examples/operator__lessequal.output rename to docs/examples/operator__lessequal.output diff --git a/doc/examples/operator__notequal.cpp b/docs/examples/operator__notequal.cpp similarity index 100% rename from doc/examples/operator__notequal.cpp rename to docs/examples/operator__notequal.cpp diff --git a/doc/examples/operator__notequal.output b/docs/examples/operator__notequal.output similarity index 100% rename from doc/examples/operator__notequal.output rename to docs/examples/operator__notequal.output diff --git a/doc/examples/operator__notequal__nullptr_t.cpp b/docs/examples/operator__notequal__nullptr_t.cpp similarity index 100% rename from doc/examples/operator__notequal__nullptr_t.cpp rename to docs/examples/operator__notequal__nullptr_t.cpp diff --git a/doc/examples/operator__notequal__nullptr_t.output b/docs/examples/operator__notequal__nullptr_t.output similarity index 100% rename from doc/examples/operator__notequal__nullptr_t.output rename to docs/examples/operator__notequal__nullptr_t.output diff --git a/doc/examples/operator__value_t.cpp b/docs/examples/operator__value_t.cpp similarity index 100% rename from doc/examples/operator__value_t.cpp rename to docs/examples/operator__value_t.cpp diff --git a/doc/examples/operator__value_t.output b/docs/examples/operator__value_t.output similarity index 100% rename from doc/examples/operator__value_t.output rename to docs/examples/operator__value_t.output diff --git a/doc/examples/operator_deserialize.cpp b/docs/examples/operator_deserialize.cpp similarity index 100% rename from doc/examples/operator_deserialize.cpp rename to docs/examples/operator_deserialize.cpp diff --git a/doc/examples/operator_deserialize.output b/docs/examples/operator_deserialize.output similarity index 100% rename from doc/examples/operator_deserialize.output rename to docs/examples/operator_deserialize.output diff --git a/doc/examples/operator_literal_json.cpp b/docs/examples/operator_literal_json.cpp similarity index 100% rename from doc/examples/operator_literal_json.cpp rename to docs/examples/operator_literal_json.cpp diff --git a/doc/examples/operator_literal_json.output b/docs/examples/operator_literal_json.output similarity index 100% rename from doc/examples/operator_literal_json.output rename to docs/examples/operator_literal_json.output diff --git a/doc/examples/operator_literal_json_pointer.cpp b/docs/examples/operator_literal_json_pointer.cpp similarity index 100% rename from doc/examples/operator_literal_json_pointer.cpp rename to docs/examples/operator_literal_json_pointer.cpp diff --git a/doc/examples/operator_literal_json_pointer.output b/docs/examples/operator_literal_json_pointer.output similarity index 100% rename from doc/examples/operator_literal_json_pointer.output rename to docs/examples/operator_literal_json_pointer.output diff --git a/doc/examples/operator_serialize.cpp b/docs/examples/operator_serialize.cpp similarity index 100% rename from doc/examples/operator_serialize.cpp rename to docs/examples/operator_serialize.cpp diff --git a/doc/examples/operator_serialize.output b/docs/examples/operator_serialize.output similarity index 100% rename from doc/examples/operator_serialize.output rename to docs/examples/operator_serialize.output diff --git a/doc/examples/operatorarray__key_type.cpp b/docs/examples/operatorarray__key_type.cpp similarity index 100% rename from doc/examples/operatorarray__key_type.cpp rename to docs/examples/operatorarray__key_type.cpp diff --git a/doc/examples/operatorarray__key_type.output b/docs/examples/operatorarray__key_type.output similarity index 100% rename from doc/examples/operatorarray__key_type.output rename to docs/examples/operatorarray__key_type.output diff --git a/doc/examples/operatorarray__key_type_const.cpp b/docs/examples/operatorarray__key_type_const.cpp similarity index 100% rename from doc/examples/operatorarray__key_type_const.cpp rename to docs/examples/operatorarray__key_type_const.cpp diff --git a/doc/examples/operatorarray__key_type_const.output b/docs/examples/operatorarray__key_type_const.output similarity index 100% rename from doc/examples/operatorarray__key_type_const.output rename to docs/examples/operatorarray__key_type_const.output diff --git a/doc/examples/operatorarray__size_type.cpp b/docs/examples/operatorarray__size_type.cpp similarity index 100% rename from doc/examples/operatorarray__size_type.cpp rename to docs/examples/operatorarray__size_type.cpp diff --git a/doc/examples/operatorarray__size_type.output b/docs/examples/operatorarray__size_type.output similarity index 100% rename from doc/examples/operatorarray__size_type.output rename to docs/examples/operatorarray__size_type.output diff --git a/doc/examples/operatorarray__size_type_const.cpp b/docs/examples/operatorarray__size_type_const.cpp similarity index 100% rename from doc/examples/operatorarray__size_type_const.cpp rename to docs/examples/operatorarray__size_type_const.cpp diff --git a/doc/examples/operatorarray__size_type_const.output b/docs/examples/operatorarray__size_type_const.output similarity index 100% rename from doc/examples/operatorarray__size_type_const.output rename to docs/examples/operatorarray__size_type_const.output diff --git a/doc/examples/operatorjson_pointer.cpp b/docs/examples/operatorjson_pointer.cpp similarity index 100% rename from doc/examples/operatorjson_pointer.cpp rename to docs/examples/operatorjson_pointer.cpp diff --git a/doc/examples/operatorjson_pointer.output b/docs/examples/operatorjson_pointer.output similarity index 100% rename from doc/examples/operatorjson_pointer.output rename to docs/examples/operatorjson_pointer.output diff --git a/doc/examples/operatorjson_pointer_const.cpp b/docs/examples/operatorjson_pointer_const.cpp similarity index 100% rename from doc/examples/operatorjson_pointer_const.cpp rename to docs/examples/operatorjson_pointer_const.cpp diff --git a/doc/examples/operatorjson_pointer_const.output b/docs/examples/operatorjson_pointer_const.output similarity index 100% rename from doc/examples/operatorjson_pointer_const.output rename to docs/examples/operatorjson_pointer_const.output diff --git a/docs/examples/ordered_json.cpp b/docs/examples/ordered_json.cpp new file mode 100644 index 000000000..effad530c --- /dev/null +++ b/docs/examples/ordered_json.cpp @@ -0,0 +1,14 @@ +#include +#include + +using ordered_json = nlohmann::ordered_json; + +int main() +{ + ordered_json j; + j["one"] = 1; + j["two"] = 2; + j["three"] = 3; + + std::cout << j.dump(2) << '\n'; +} diff --git a/docs/examples/ordered_json.output b/docs/examples/ordered_json.output new file mode 100644 index 000000000..120cbb284 --- /dev/null +++ b/docs/examples/ordered_json.output @@ -0,0 +1,5 @@ +{ + "one": 1, + "two": 2, + "three": 3 +} diff --git a/doc/examples/ordered_map.cpp b/docs/examples/ordered_map.cpp similarity index 100% rename from doc/examples/ordered_map.cpp rename to docs/examples/ordered_map.cpp diff --git a/doc/examples/ordered_map.output b/docs/examples/ordered_map.output similarity index 100% rename from doc/examples/ordered_map.output rename to docs/examples/ordered_map.output diff --git a/doc/examples/other_error.cpp b/docs/examples/other_error.cpp similarity index 100% rename from doc/examples/other_error.cpp rename to docs/examples/other_error.cpp diff --git a/doc/examples/other_error.output b/docs/examples/other_error.output similarity index 100% rename from doc/examples/other_error.output rename to docs/examples/other_error.output diff --git a/doc/examples/out_of_range.cpp b/docs/examples/out_of_range.cpp similarity index 100% rename from doc/examples/out_of_range.cpp rename to docs/examples/out_of_range.cpp diff --git a/doc/examples/out_of_range.output b/docs/examples/out_of_range.output similarity index 100% rename from doc/examples/out_of_range.output rename to docs/examples/out_of_range.output diff --git a/doc/examples/parse__allow_exceptions.cpp b/docs/examples/parse__allow_exceptions.cpp similarity index 100% rename from doc/examples/parse__allow_exceptions.cpp rename to docs/examples/parse__allow_exceptions.cpp diff --git a/doc/examples/parse__allow_exceptions.output b/docs/examples/parse__allow_exceptions.output similarity index 100% rename from doc/examples/parse__allow_exceptions.output rename to docs/examples/parse__allow_exceptions.output diff --git a/doc/examples/parse__array__parser_callback_t.cpp b/docs/examples/parse__array__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__array__parser_callback_t.cpp rename to docs/examples/parse__array__parser_callback_t.cpp diff --git a/doc/examples/parse__array__parser_callback_t.output b/docs/examples/parse__array__parser_callback_t.output similarity index 100% rename from doc/examples/parse__array__parser_callback_t.output rename to docs/examples/parse__array__parser_callback_t.output diff --git a/doc/examples/parse__contiguouscontainer__parser_callback_t.cpp b/docs/examples/parse__contiguouscontainer__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__contiguouscontainer__parser_callback_t.cpp rename to docs/examples/parse__contiguouscontainer__parser_callback_t.cpp diff --git a/doc/examples/parse__contiguouscontainer__parser_callback_t.output b/docs/examples/parse__contiguouscontainer__parser_callback_t.output similarity index 100% rename from doc/examples/parse__contiguouscontainer__parser_callback_t.output rename to docs/examples/parse__contiguouscontainer__parser_callback_t.output diff --git a/doc/examples/parse__istream__parser_callback_t.cpp b/docs/examples/parse__istream__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__istream__parser_callback_t.cpp rename to docs/examples/parse__istream__parser_callback_t.cpp diff --git a/doc/examples/parse__istream__parser_callback_t.output b/docs/examples/parse__istream__parser_callback_t.output similarity index 100% rename from doc/examples/parse__istream__parser_callback_t.output rename to docs/examples/parse__istream__parser_callback_t.output diff --git a/doc/examples/parse__iterator_pair.cpp b/docs/examples/parse__iterator_pair.cpp similarity index 100% rename from doc/examples/parse__iterator_pair.cpp rename to docs/examples/parse__iterator_pair.cpp diff --git a/doc/examples/parse__iterator_pair.link b/docs/examples/parse__iterator_pair.link similarity index 100% rename from doc/examples/parse__iterator_pair.link rename to docs/examples/parse__iterator_pair.link diff --git a/doc/examples/parse__iterator_pair.output b/docs/examples/parse__iterator_pair.output similarity index 100% rename from doc/examples/parse__iterator_pair.output rename to docs/examples/parse__iterator_pair.output diff --git a/doc/examples/parse__pointers.cpp b/docs/examples/parse__pointers.cpp similarity index 100% rename from doc/examples/parse__pointers.cpp rename to docs/examples/parse__pointers.cpp diff --git a/doc/examples/parse__pointers.link b/docs/examples/parse__pointers.link similarity index 100% rename from doc/examples/parse__pointers.link rename to docs/examples/parse__pointers.link diff --git a/doc/examples/parse__pointers.output b/docs/examples/parse__pointers.output similarity index 100% rename from doc/examples/parse__pointers.output rename to docs/examples/parse__pointers.output diff --git a/doc/examples/parse__string__parser_callback_t.cpp b/docs/examples/parse__string__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__string__parser_callback_t.cpp rename to docs/examples/parse__string__parser_callback_t.cpp diff --git a/doc/examples/parse__string__parser_callback_t.output b/docs/examples/parse__string__parser_callback_t.output similarity index 100% rename from doc/examples/parse__string__parser_callback_t.output rename to docs/examples/parse__string__parser_callback_t.output diff --git a/doc/examples/parse_error.cpp b/docs/examples/parse_error.cpp similarity index 100% rename from doc/examples/parse_error.cpp rename to docs/examples/parse_error.cpp diff --git a/doc/examples/parse_error.output b/docs/examples/parse_error.output similarity index 100% rename from doc/examples/parse_error.output rename to docs/examples/parse_error.output diff --git a/doc/examples/patch.cpp b/docs/examples/patch.cpp similarity index 100% rename from doc/examples/patch.cpp rename to docs/examples/patch.cpp diff --git a/doc/examples/patch.output b/docs/examples/patch.output similarity index 100% rename from doc/examples/patch.output rename to docs/examples/patch.output diff --git a/doc/examples/push_back.cpp b/docs/examples/push_back.cpp similarity index 100% rename from doc/examples/push_back.cpp rename to docs/examples/push_back.cpp diff --git a/doc/examples/push_back.output b/docs/examples/push_back.output similarity index 100% rename from doc/examples/push_back.output rename to docs/examples/push_back.output diff --git a/doc/examples/push_back__initializer_list.cpp b/docs/examples/push_back__initializer_list.cpp similarity index 100% rename from doc/examples/push_back__initializer_list.cpp rename to docs/examples/push_back__initializer_list.cpp diff --git a/doc/examples/push_back__initializer_list.output b/docs/examples/push_back__initializer_list.output similarity index 100% rename from doc/examples/push_back__initializer_list.output rename to docs/examples/push_back__initializer_list.output diff --git a/doc/examples/push_back__object_t__value.cpp b/docs/examples/push_back__object_t__value.cpp similarity index 100% rename from doc/examples/push_back__object_t__value.cpp rename to docs/examples/push_back__object_t__value.cpp diff --git a/doc/examples/push_back__object_t__value.output b/docs/examples/push_back__object_t__value.output similarity index 100% rename from doc/examples/push_back__object_t__value.output rename to docs/examples/push_back__object_t__value.output diff --git a/doc/examples/rbegin.cpp b/docs/examples/rbegin.cpp similarity index 100% rename from doc/examples/rbegin.cpp rename to docs/examples/rbegin.cpp diff --git a/doc/examples/rbegin.output b/docs/examples/rbegin.output similarity index 100% rename from doc/examples/rbegin.output rename to docs/examples/rbegin.output diff --git a/doc/examples/rend.cpp b/docs/examples/rend.cpp similarity index 100% rename from doc/examples/rend.cpp rename to docs/examples/rend.cpp diff --git a/doc/examples/rend.output b/docs/examples/rend.output similarity index 100% rename from doc/examples/rend.output rename to docs/examples/rend.output diff --git a/doc/examples/sax_parse.cpp b/docs/examples/sax_parse.cpp similarity index 65% rename from doc/examples/sax_parse.cpp rename to docs/examples/sax_parse.cpp index 45273eb6c..8602687e3 100644 --- a/doc/examples/sax_parse.cpp +++ b/docs/examples/sax_parse.cpp @@ -6,7 +6,7 @@ using json = nlohmann::json; // a simple event consumer that collects string representations of the passed -// values; not inheriting from json::json_sax_t is not required, but can +// values; note inheriting from json::json_sax_t is not required, but can // help not to forget a required function class sax_event_consumer : public json::json_sax_t { @@ -15,79 +15,79 @@ class sax_event_consumer : public json::json_sax_t bool null() override { - events.push_back("value: null"); + events.push_back("null()"); return true; } bool boolean(bool val) override { - events.push_back("value: " + std::string(val ? "true" : "false")); + events.push_back("boolean(val=" + std::string(val ? "true" : "false") + ")"); return true; } bool number_integer(number_integer_t val) override { - events.push_back("value: " + std::to_string(val)); + events.push_back("number_integer(val=" + std::to_string(val) + ")"); return true; } bool number_unsigned(number_unsigned_t val) override { - events.push_back("value: " + std::to_string(val)); + events.push_back("number_unsigned(val=" + std::to_string(val) + ")"); return true; } bool number_float(number_float_t val, const string_t& s) override { - events.push_back("value: " + s); + events.push_back("number_float(val=" + std::to_string(val) + ", s=" + s + ")"); return true; } bool string(string_t& val) override { - events.push_back("value: " + val); + events.push_back("string(val=" + val + ")"); return true; } bool start_object(std::size_t elements) override { - events.push_back("start: object"); + events.push_back("start_object(elements=" + std::to_string(elements) + ")"); return true; } bool end_object() override { - events.push_back("end: object"); + events.push_back("end_object()"); return true; } bool start_array(std::size_t elements) override { - events.push_back("start: array"); + events.push_back("start_array(elements=" + std::to_string(elements) + ")"); return true; } bool end_array() override { - events.push_back("end: array"); + events.push_back("end_array()"); return true; } bool key(string_t& val) override { - events.push_back("key: " + val); + events.push_back("key(val=" + val + ")"); return true; } bool binary(json::binary_t& val) override { - events.push_back("binary"); + events.push_back("binary(val=[...])"); return true; } bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) override { - events.push_back("error: " + std::string(ex.what())); + events.push_back("parse_error(position=" + std::to_string(position) + ", last_token=" + last_token + ",\n ex=" + std::string(ex.what()) + ")"); return false; } }; @@ -107,22 +107,23 @@ int main() "Width": 100 }, "Animated" : false, - "IDs": [116, 943, 234, 38793], + "IDs": [116, 943, 234, -38793], + "DeletionDate": null, "Distance": 12.723374634 } - } + }] )"; // create a SAX event consumer object sax_event_consumer sec; - // parse and serialize JSON + // parse JSON bool result = json::sax_parse(text, &sec); // output the recorded events for (auto& event : sec.events) { - std::cout << "(" << event << ") "; + std::cout << event << "\n"; } // output the result of sax_parse diff --git a/docs/examples/sax_parse.output b/docs/examples/sax_parse.output new file mode 100644 index 000000000..dd2fc2f05 --- /dev/null +++ b/docs/examples/sax_parse.output @@ -0,0 +1,37 @@ +start_object(elements=18446744073709551615) +key(val=Image) +start_object(elements=18446744073709551615) +key(val=Width) +number_unsigned(val=800) +key(val=Height) +number_unsigned(val=600) +key(val=Title) +string(val=View from 15th Floor) +key(val=Thumbnail) +start_object(elements=18446744073709551615) +key(val=Url) +string(val=http://www.example.com/image/481989943) +key(val=Height) +number_unsigned(val=125) +key(val=Width) +number_unsigned(val=100) +end_object() +key(val=Animated) +boolean(val=false) +key(val=IDs) +start_array(elements=18446744073709551615) +number_unsigned(val=116) +number_unsigned(val=943) +number_unsigned(val=234) +number_integer(val=-38793) +end_array() +key(val=DeletionDate) +null() +key(val=Distance) +number_float(val=12.723375, s=12.723374634) +end_object() +end_object() +parse_error(position=460, last_token=12.723374634 } }], + ex=[json.exception.parse_error.101] parse error at line 17, column 6: syntax error while parsing value - unexpected ']'; expected end of input) + +result: false diff --git a/docs/examples/sax_parse__binary.cpp b/docs/examples/sax_parse__binary.cpp new file mode 100644 index 000000000..08bc85df6 --- /dev/null +++ b/docs/examples/sax_parse__binary.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include + +using json = nlohmann::json; + +// a simple event consumer that collects string representations of the passed +// values; note inheriting from json::json_sax_t is not required, but can +// help not to forget a required function +class sax_event_consumer : public json::json_sax_t +{ + public: + std::vector events; + + bool null() override + { + events.push_back("null()"); + return true; + } + + bool boolean(bool val) override + { + events.push_back("boolean(val=" + std::string(val ? "true" : "false") + ")"); + return true; + } + + bool number_integer(number_integer_t val) override + { + events.push_back("number_integer(val=" + std::to_string(val) + ")"); + return true; + } + + bool number_unsigned(number_unsigned_t val) override + { + events.push_back("number_unsigned(val=" + std::to_string(val) + ")"); + return true; + } + + bool number_float(number_float_t val, const string_t& s) override + { + events.push_back("number_float(val=" + std::to_string(val) + ", s=" + s + ")"); + return true; + } + + bool string(string_t& val) override + { + events.push_back("string(val=" + val + ")"); + return true; + } + + bool start_object(std::size_t elements) override + { + events.push_back("start_object(elements=" + std::to_string(elements) + ")"); + return true; + } + + bool end_object() override + { + events.push_back("end_object()"); + return true; + } + + bool start_array(std::size_t elements) override + { + events.push_back("start_array(elements=" + std::to_string(elements) + ")"); + return true; + } + + bool end_array() override + { + events.push_back("end_array()"); + return true; + } + + bool key(string_t& val) override + { + events.push_back("key(val=" + val + ")"); + return true; + } + + bool binary(json::binary_t& val) override + { + events.push_back("binary(val=[...])"); + return true; + } + + bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) override + { + events.push_back("parse_error(position=" + std::to_string(position) + ", last_token=" + last_token + ",\n ex=" + std::string(ex.what()) + ")"); + return false; + } +}; + +int main() +{ + // CBOR byte string + std::vector vec = {{0x44, 0xcA, 0xfe, 0xba, 0xbe}}; + + // create a SAX event consumer object + sax_event_consumer sec; + + // parse CBOR + bool result = json::sax_parse(vec, &sec, json::input_format_t::cbor); + + // output the recorded events + for (auto& event : sec.events) + { + std::cout << event << "\n"; + } + + // output the result of sax_parse + std::cout << "\nresult: " << std::boolalpha << result << std::endl; +} diff --git a/docs/examples/sax_parse__binary.output b/docs/examples/sax_parse__binary.output new file mode 100644 index 000000000..f88089610 --- /dev/null +++ b/docs/examples/sax_parse__binary.output @@ -0,0 +1,3 @@ +binary(val=[...]) + +result: true diff --git a/doc/examples/size.cpp b/docs/examples/size.cpp similarity index 100% rename from doc/examples/size.cpp rename to docs/examples/size.cpp diff --git a/doc/examples/size.output b/docs/examples/size.output similarity index 100% rename from doc/examples/size.output rename to docs/examples/size.output diff --git a/doc/examples/std_hash.cpp b/docs/examples/std_hash.cpp similarity index 100% rename from doc/examples/std_hash.cpp rename to docs/examples/std_hash.cpp diff --git a/doc/examples/std_hash.output b/docs/examples/std_hash.output similarity index 100% rename from doc/examples/std_hash.output rename to docs/examples/std_hash.output diff --git a/doc/examples/std_swap.cpp b/docs/examples/std_swap.cpp similarity index 100% rename from doc/examples/std_swap.cpp rename to docs/examples/std_swap.cpp diff --git a/doc/examples/std_swap.output b/docs/examples/std_swap.output similarity index 100% rename from doc/examples/std_swap.output rename to docs/examples/std_swap.output diff --git a/doc/examples/string_t.cpp b/docs/examples/string_t.cpp similarity index 100% rename from doc/examples/string_t.cpp rename to docs/examples/string_t.cpp diff --git a/doc/examples/string_t.output b/docs/examples/string_t.output similarity index 100% rename from doc/examples/string_t.output rename to docs/examples/string_t.output diff --git a/doc/examples/swap__array_t.cpp b/docs/examples/swap__array_t.cpp similarity index 100% rename from doc/examples/swap__array_t.cpp rename to docs/examples/swap__array_t.cpp diff --git a/doc/examples/swap__array_t.output b/docs/examples/swap__array_t.output similarity index 100% rename from doc/examples/swap__array_t.output rename to docs/examples/swap__array_t.output diff --git a/doc/examples/swap__binary_t.cpp b/docs/examples/swap__binary_t.cpp similarity index 100% rename from doc/examples/swap__binary_t.cpp rename to docs/examples/swap__binary_t.cpp diff --git a/doc/examples/swap__binary_t.output b/docs/examples/swap__binary_t.output similarity index 100% rename from doc/examples/swap__binary_t.output rename to docs/examples/swap__binary_t.output diff --git a/doc/examples/swap__object_t.cpp b/docs/examples/swap__object_t.cpp similarity index 100% rename from doc/examples/swap__object_t.cpp rename to docs/examples/swap__object_t.cpp diff --git a/doc/examples/swap__object_t.output b/docs/examples/swap__object_t.output similarity index 100% rename from doc/examples/swap__object_t.output rename to docs/examples/swap__object_t.output diff --git a/doc/examples/swap__reference.cpp b/docs/examples/swap__reference.cpp similarity index 100% rename from doc/examples/swap__reference.cpp rename to docs/examples/swap__reference.cpp diff --git a/doc/examples/swap__reference.output b/docs/examples/swap__reference.output similarity index 100% rename from doc/examples/swap__reference.output rename to docs/examples/swap__reference.output diff --git a/doc/examples/swap__string_t.cpp b/docs/examples/swap__string_t.cpp similarity index 100% rename from doc/examples/swap__string_t.cpp rename to docs/examples/swap__string_t.cpp diff --git a/doc/examples/swap__string_t.output b/docs/examples/swap__string_t.output similarity index 100% rename from doc/examples/swap__string_t.output rename to docs/examples/swap__string_t.output diff --git a/docs/examples/to_bjdata.cpp b/docs/examples/to_bjdata.cpp new file mode 100644 index 000000000..0bfe33323 --- /dev/null +++ b/docs/examples/to_bjdata.cpp @@ -0,0 +1,63 @@ +#include +#include +#include + +using json = nlohmann::json; + +// function to print BJData's diagnostic format +void print_byte(uint8_t byte) +{ + if (32 < byte and byte < 128) + { + std::cout << (char)byte; + } + else + { + std::cout << (int)byte; + } +} + +int main() +{ + // create a JSON value + json j = R"({"compact": true, "schema": false})"_json; + + // serialize it to BJData + std::vector v = json::to_bjdata(j); + + // print the vector content + for (auto& byte : v) + { + print_byte(byte); + } + std::cout << std::endl; + + // create an array of numbers + json array = {1, 2, 3, 4, 5, 6, 7, 8}; + + // serialize it to BJData using default representation + std::vector v_array = json::to_bjdata(array); + // serialize it to BJData using size optimization + std::vector v_array_size = json::to_bjdata(array, true); + // serialize it to BJData using type optimization + std::vector v_array_size_and_type = json::to_bjdata(array, true, true); + + // print the vector contents + for (auto& byte : v_array) + { + print_byte(byte); + } + std::cout << std::endl; + + for (auto& byte : v_array_size) + { + print_byte(byte); + } + std::cout << std::endl; + + for (auto& byte : v_array_size_and_type) + { + print_byte(byte); + } + std::cout << std::endl; +} diff --git a/doc/examples/to_ubjson.output b/docs/examples/to_bjdata.output similarity index 100% rename from doc/examples/to_ubjson.output rename to docs/examples/to_bjdata.output diff --git a/doc/examples/to_bson.cpp b/docs/examples/to_bson.cpp similarity index 100% rename from doc/examples/to_bson.cpp rename to docs/examples/to_bson.cpp diff --git a/doc/examples/to_bson.output b/docs/examples/to_bson.output similarity index 100% rename from doc/examples/to_bson.output rename to docs/examples/to_bson.output diff --git a/doc/examples/to_cbor.cpp b/docs/examples/to_cbor.cpp similarity index 100% rename from doc/examples/to_cbor.cpp rename to docs/examples/to_cbor.cpp diff --git a/doc/examples/to_cbor.output b/docs/examples/to_cbor.output similarity index 100% rename from doc/examples/to_cbor.output rename to docs/examples/to_cbor.output diff --git a/doc/examples/to_msgpack.cpp b/docs/examples/to_msgpack.cpp similarity index 100% rename from doc/examples/to_msgpack.cpp rename to docs/examples/to_msgpack.cpp diff --git a/doc/examples/to_msgpack.output b/docs/examples/to_msgpack.output similarity index 100% rename from doc/examples/to_msgpack.output rename to docs/examples/to_msgpack.output diff --git a/doc/examples/to_string.cpp b/docs/examples/to_string.cpp similarity index 100% rename from doc/examples/to_string.cpp rename to docs/examples/to_string.cpp diff --git a/doc/examples/to_string.output b/docs/examples/to_string.output similarity index 100% rename from doc/examples/to_string.output rename to docs/examples/to_string.output diff --git a/doc/examples/to_ubjson.cpp b/docs/examples/to_ubjson.cpp similarity index 100% rename from doc/examples/to_ubjson.cpp rename to docs/examples/to_ubjson.cpp diff --git a/docs/examples/to_ubjson.output b/docs/examples/to_ubjson.output new file mode 100644 index 000000000..087980cb9 --- /dev/null +++ b/docs/examples/to_ubjson.output @@ -0,0 +1,4 @@ +{i7compactTi6schemaF} +[i1i2i3i4i5i6i7i8] +[#i8i1i2i3i4i5i6i7i8 +[$i#i812345678 diff --git a/doc/examples/type.cpp b/docs/examples/type.cpp similarity index 100% rename from doc/examples/type.cpp rename to docs/examples/type.cpp diff --git a/doc/examples/type.output b/docs/examples/type.output similarity index 100% rename from doc/examples/type.output rename to docs/examples/type.output diff --git a/doc/examples/type_error.cpp b/docs/examples/type_error.cpp similarity index 100% rename from doc/examples/type_error.cpp rename to docs/examples/type_error.cpp diff --git a/doc/examples/type_error.output b/docs/examples/type_error.output similarity index 100% rename from doc/examples/type_error.output rename to docs/examples/type_error.output diff --git a/doc/examples/type_name.cpp b/docs/examples/type_name.cpp similarity index 100% rename from doc/examples/type_name.cpp rename to docs/examples/type_name.cpp diff --git a/doc/examples/type_name.output b/docs/examples/type_name.output similarity index 100% rename from doc/examples/type_name.output rename to docs/examples/type_name.output diff --git a/doc/examples/unflatten.cpp b/docs/examples/unflatten.cpp similarity index 100% rename from doc/examples/unflatten.cpp rename to docs/examples/unflatten.cpp diff --git a/doc/examples/unflatten.output b/docs/examples/unflatten.output similarity index 100% rename from doc/examples/unflatten.output rename to docs/examples/unflatten.output diff --git a/doc/examples/update.cpp b/docs/examples/update.cpp similarity index 100% rename from doc/examples/update.cpp rename to docs/examples/update.cpp diff --git a/doc/examples/update.output b/docs/examples/update.output similarity index 100% rename from doc/examples/update.output rename to docs/examples/update.output diff --git a/doc/examples/update__range.cpp b/docs/examples/update__range.cpp similarity index 100% rename from doc/examples/update__range.cpp rename to docs/examples/update__range.cpp diff --git a/doc/examples/update__range.output b/docs/examples/update__range.output similarity index 100% rename from doc/examples/update__range.output rename to docs/examples/update__range.output diff --git a/doc/index.md b/docs/index.md similarity index 100% rename from doc/index.md rename to docs/index.md diff --git a/doc/json.gif b/docs/json.gif similarity index 100% rename from doc/json.gif rename to docs/json.gif diff --git a/doc/mkdocs/Makefile b/docs/mkdocs/Makefile similarity index 57% rename from doc/mkdocs/Makefile rename to docs/mkdocs/Makefile index 3d3d5e7c6..3f894d098 100644 --- a/doc/mkdocs/Makefile +++ b/docs/mkdocs/Makefile @@ -1,18 +1,21 @@ # serve the site locally -serve: prepare_files +serve: prepare_files style_check venv/bin/mkdocs serve -build: prepare_files +serve_dirty: prepare_files style_check + venv/bin/mkdocs serve --dirtyreload + +build: prepare_files style_check venv/bin/mkdocs build -# create files that are not versioned inside the mkdocs folder +# create files that are not versioned inside the mkdocs folder (images, examples) prepare_files: clean - # create subfolders mkdir docs/examples - # copy images - cp -vr ../json.gif docs/images - # copy examples - cp -vr ../examples/*.cpp ../examples/*.output docs/examples + cp -r ../json.gif docs/images + cp -r ../examples/*.cpp ../examples/*.output docs/examples + +style_check: + @cd docs ; python3 ../scripts/check_structure.py # clean subfolders clean: diff --git a/doc/mkdocs/docs/api/adl_serializer/from_json.md b/docs/mkdocs/docs/api/adl_serializer/from_json.md similarity index 100% rename from doc/mkdocs/docs/api/adl_serializer/from_json.md rename to docs/mkdocs/docs/api/adl_serializer/from_json.md diff --git a/doc/mkdocs/docs/api/adl_serializer/index.md b/docs/mkdocs/docs/api/adl_serializer/index.md similarity index 100% rename from doc/mkdocs/docs/api/adl_serializer/index.md rename to docs/mkdocs/docs/api/adl_serializer/index.md diff --git a/doc/mkdocs/docs/api/adl_serializer/to_json.md b/docs/mkdocs/docs/api/adl_serializer/to_json.md similarity index 100% rename from doc/mkdocs/docs/api/adl_serializer/to_json.md rename to docs/mkdocs/docs/api/adl_serializer/to_json.md diff --git a/doc/mkdocs/docs/api/basic_json/accept.md b/docs/mkdocs/docs/api/basic_json/accept.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/accept.md rename to docs/mkdocs/docs/api/basic_json/accept.md diff --git a/doc/mkdocs/docs/api/basic_json/array.md b/docs/mkdocs/docs/api/basic_json/array.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/array.md rename to docs/mkdocs/docs/api/basic_json/array.md diff --git a/doc/mkdocs/docs/api/basic_json/array_t.md b/docs/mkdocs/docs/api/basic_json/array_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/array_t.md rename to docs/mkdocs/docs/api/basic_json/array_t.md diff --git a/doc/mkdocs/docs/api/basic_json/at.md b/docs/mkdocs/docs/api/basic_json/at.md similarity index 80% rename from doc/mkdocs/docs/api/basic_json/at.md rename to docs/mkdocs/docs/api/basic_json/at.md index fc518f46e..3eea8dd15 100644 --- a/doc/mkdocs/docs/api/basic_json/at.md +++ b/docs/mkdocs/docs/api/basic_json/at.md @@ -10,13 +10,28 @@ reference at(const typename object_t::key_type& key); const_reference at(const typename object_t::key_type& key) const; // (3) +template +reference at(KeyType&& key); +template +const_reference at(KeyType&& key) const; + +// (4) reference at(const json_pointer& ptr); const_reference at(const json_pointer& ptr) const; ``` 1. Returns a reference to the array element at specified location `idx`, with bounds checking. -2. Returns a reference to the object element at with specified key `key`, with bounds checking. -3. Returns a reference to the element at with specified JSON pointer `ptr`, with bounds checking. +2. Returns a reference to the object element with specified key `key`, with bounds checking. +3. See 2. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. +4. Returns a reference to the element at specified JSON pointer `ptr`, with bounds checking. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). ## Parameters @@ -25,15 +40,16 @@ const_reference at(const json_pointer& ptr) const; `key` (in) : object key of the elements to access - + `ptr` (in) : JSON pointer to the desired element - + ## Return value 1. reference to the element at index `idx` 2. reference to the element at key `key` -3. reference to the element pointed to by `ptr` +3. reference to the element at key `key` +4. reference to the element pointed to by `ptr` ## Exception safety @@ -51,7 +67,8 @@ Strong exception safety: if an exception occurs, the original value stays intact in this case, calling `at` with a key makes no sense. See example below. - Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if the key `key` is not stored in the object; that is, `find(key) == end()`. See example below. -3. The function can throw the following exceptions: +3. See 2. +4. The function can throw the following exceptions: - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in the passed JSON pointer `ptr` begins with '0'. See example below. - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed @@ -68,9 +85,10 @@ Strong exception safety: if an exception occurs, the original value stays intact ## Complexity -1. Constant +1. Constant. 2. Logarithmic in the size of the container. -3. Constant +3. Logarithmic in the size of the container. +4. Logarithmic in the size of the container. ## Examples @@ -134,7 +152,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/at__object_t_key_type_const.output" ``` -??? example "Example (3) access specified element via JSON Pointer" +??? example "Example (4) access specified element via JSON Pointer" The example below shows how object elements can be read and written using `at()`. It also demonstrates the different exceptions that can be thrown. @@ -149,7 +167,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/at_json_pointer.output" ``` -??? example "Example (3) access specified element via JSON Pointer" +??? example "Example (4) access specified element via JSON Pointer" The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions that can be thrown. @@ -166,6 +184,7 @@ Strong exception safety: if an exception occurs, the original value stays intact ## See also +- documentation on [checked access](../../features/element_access/checked_access.md) - see [`operator[]`](operator%5B%5D.md) for unchecked access by reference - see [`value`](value.md) for access with default value @@ -173,4 +192,5 @@ Strong exception safety: if an exception occurs, the original value stays intact 1. Added in version 1.0.0. 2. Added in version 1.0.0. -3. Added in version 2.0.0. +3. Added in version 3.11.0. +4. Added in version 2.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/back.md b/docs/mkdocs/docs/api/basic_json/back.md similarity index 89% rename from doc/mkdocs/docs/api/basic_json/back.md rename to docs/mkdocs/docs/api/basic_json/back.md index 96e1dec75..1a715284d 100644 --- a/doc/mkdocs/docs/api/basic_json/back.md +++ b/docs/mkdocs/docs/api/basic_json/back.md @@ -35,9 +35,9 @@ Constant. ## Notes -!!! danger +!!! info "Precondition" - Calling `back` on an empty array or object is undefined behavior and is **guarded by an assertion**! + The array or object must not be empty. Calling `back` on an empty array or object yields undefined behavior. ## Examples diff --git a/doc/mkdocs/docs/api/basic_json/basic_json.md b/docs/mkdocs/docs/api/basic_json/basic_json.md similarity index 96% rename from doc/mkdocs/docs/api/basic_json/basic_json.md rename to docs/mkdocs/docs/api/basic_json/basic_json.md index ab3fea470..365cd7c22 100644 --- a/doc/mkdocs/docs/api/basic_json/basic_json.md +++ b/docs/mkdocs/docs/api/basic_json/basic_json.md @@ -201,16 +201,16 @@ basic_json(basic_json&& other) noexcept; ## Exceptions -1. / +1. (none) 2. The function does not throw exceptions. -3. / -4. / +3. (none) +4. (none) 5. The function can throw the following exceptions: - Throws [`type_error.301`](../../home/exceptions.md#jsonexceptiontype_error301) if `type_deduction` is `#!cpp false`, `manual_type` is `value_t::object`, but `init` contains an element which is not a pair whose first element is a string. In this case, the constructor could not create an object. If `type_deduction` would have been `#!cpp true`, an array would have been created. See `object(initializer_list_t)` for an example. -6. / +6. (none) 7. The function can throw the following exceptions: - Throws [`invalid_iterator.201`](../../home/exceptions.md#jsonexceptioninvalid_iterator201) if iterators `first` and `last` are not compatible (i.e., do not belong to the same JSON value). In this case, the range @@ -220,7 +220,7 @@ basic_json(basic_json&& other) noexcept; element anymore. In this case, the range `[first, last)` is undefined. See example code below. - Throws [`invalid_iterator.206`](../../home/exceptions.md#jsonexceptioninvalid_iterator206) if iterators `first` and `last` belong to a `#!json null` value. In this case, the range `[first, last)` is undefined. -8. / +8. (none) 9. The function does not throw exceptions. ## Complexity @@ -241,7 +241,7 @@ basic_json(basic_json&& other) noexcept; - Overload 5: - !!! note + !!! note "Empty initializer list" When used without parentheses around an empty initializer list, `basic_json()` is called instead of this function, yielding the JSON `#!json null` value. @@ -250,17 +250,15 @@ basic_json(basic_json&& other) noexcept; !!! info "Preconditions" - - Iterators `first` and `last` must be initialized. **This precondition is enforced with an assertion (see - warning).** If assertions are switched off, a violation of this precondition yields undefined behavior. + - Iterators `first` and `last` must be initialized. **This precondition is enforced with a + [runtime assertion](../../features/assertions.md). - Range `[first, last)` is valid. Usually, this precondition cannot be checked efficiently. Only certain edge cases are detected; see the description of the exceptions above. A violation of this precondition yields undefined behavior. - !!! warning + !!! danger "Runtime assertion" - A precondition is enforced with a runtime assertion that will result in calling `std::abort` if this - precondition is not met. Assertions can be disabled by defining `NDEBUG` at compile time. See - for more information. + A precondition is enforced with a [runtime assertion](../../features/assertions.md). - Overload 8: diff --git a/doc/mkdocs/docs/api/basic_json/begin.md b/docs/mkdocs/docs/api/basic_json/begin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/begin.md rename to docs/mkdocs/docs/api/basic_json/begin.md diff --git a/doc/mkdocs/docs/api/basic_json/binary.md b/docs/mkdocs/docs/api/basic_json/binary.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/binary.md rename to docs/mkdocs/docs/api/basic_json/binary.md diff --git a/doc/mkdocs/docs/api/basic_json/binary_t.md b/docs/mkdocs/docs/api/basic_json/binary_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/binary_t.md rename to docs/mkdocs/docs/api/basic_json/binary_t.md diff --git a/doc/mkdocs/docs/api/basic_json/boolean_t.md b/docs/mkdocs/docs/api/basic_json/boolean_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/boolean_t.md rename to docs/mkdocs/docs/api/basic_json/boolean_t.md diff --git a/doc/mkdocs/docs/api/basic_json/cbegin.md b/docs/mkdocs/docs/api/basic_json/cbegin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/cbegin.md rename to docs/mkdocs/docs/api/basic_json/cbegin.md diff --git a/doc/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md b/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md similarity index 57% rename from doc/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md rename to docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md index 6622d8aca..e19c3edd9 100644 --- a/doc/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md +++ b/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md @@ -20,6 +20,23 @@ ignore store : store tagged values as binary container with subtype (for bytes 0xd8..0xdb) +## Examples + +??? example + + The example below shows how the different values of the `cbor_tag_handler_t` influence the behavior of + [`from_cbor`](from_cbor.md) when reading a tagged byte string. + + ```cpp + --8<-- "examples/cbor_tag_handler_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/cbor_tag_handler_t.output" + ``` + ## Version history - Added in version 3.9.0. Added value `store` in 3.10.0. diff --git a/doc/mkdocs/docs/api/basic_json/cend.md b/docs/mkdocs/docs/api/basic_json/cend.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/cend.md rename to docs/mkdocs/docs/api/basic_json/cend.md diff --git a/doc/mkdocs/docs/api/basic_json/clear.md b/docs/mkdocs/docs/api/basic_json/clear.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/clear.md rename to docs/mkdocs/docs/api/basic_json/clear.md diff --git a/doc/mkdocs/docs/api/basic_json/contains.md b/docs/mkdocs/docs/api/basic_json/contains.md similarity index 56% rename from doc/mkdocs/docs/api/basic_json/contains.md rename to docs/mkdocs/docs/api/basic_json/contains.md index 8463f4ea9..e6d9df85c 100644 --- a/doc/mkdocs/docs/api/basic_json/contains.md +++ b/docs/mkdocs/docs/api/basic_json/contains.md @@ -2,21 +2,28 @@ ```cpp // (1) -template -bool contains(KeyT && key) const; +bool contains(const typename object_t::key_type& key) const; // (2) +template +bool contains(KeyType&& key) const; + +// (3) bool contains(const json_pointer& ptr) const; ``` -1. Check whether an element exists in a JSON object with key equivalent to `key`. If the element is not found or the +1. Check whether an element exists in a JSON object with a key equivalent to `key`. If the element is not found or the JSON value is not an object, `#!cpp false` is returned. -2. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value. +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. +3. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value. ## Template parameters -`KeyT` -: A type for an object key other than `basic_json::json_pointer`. +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). ## Parameters @@ -30,7 +37,8 @@ bool contains(const json_pointer& ptr) const; 1. `#!cpp true` if an element with specified `key` exists. If no such element with such key is found or the JSON value is not an object, `#!cpp false` is returned. -2. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise. +2. See 1. +3. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise. ## Exception safety @@ -39,7 +47,8 @@ Strong exception safety: if an exception occurs, the original value stays intact ## Exceptions 1. The function does not throw exceptions. -2. The function can throw the following exceptions: +2. The function does not throw exceptions. +3. The function can throw the following exceptions: - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index begins with `0`. - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index was not a @@ -51,8 +60,8 @@ Logarithmic in the size of the JSON object. ## Notes -1. This method always returns `#!cpp false` when executed on a JSON type that is not an object. -2. This method can be executed on any JSON value type. +- This method always returns `#!cpp false` when executed on a JSON type that is not an object. +- This method can be executed on any JSON value type. !!! info "Postconditions" @@ -74,7 +83,7 @@ Logarithmic in the size of the JSON object. --8<-- "examples/contains.output" ``` -??? example "Example (1) check with JSON pointer" +??? example "Example (3) check with JSON pointer" The example shows how `contains()` is used. @@ -90,5 +99,6 @@ Logarithmic in the size of the JSON object. ## Version history -1. Added in version 3.6.0. -2. Added in version 3.7.0. +1. Added in version 3.11.0. +2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0. +3. Added in version 3.7.0. diff --git a/docs/mkdocs/docs/api/basic_json/count.md b/docs/mkdocs/docs/api/basic_json/count.md new file mode 100644 index 000000000..de135be21 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/count.md @@ -0,0 +1,64 @@ +# nlohmann::basic_json::count + +```cpp +// (1) +size_type count(const typename object_t::key_type& key) const; + +// (2) +template +size_type count(KeyType&& key) const; +``` + +1. Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will + always be `0` (`key` was not found) or `1` (`key` was found). +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). + +## Parameters + +`key` (in) +: key value of the element to count. + +## Return value + +Number of elements with key `key`. If the JSON value is not an object, the return value will be `0`. + +## Exception safety + +Strong exception safety: if an exception occurs, the original value stays intact. + +## Complexity + +Logarithmic in the size of the JSON object. + +## Notes + +This method always returns `0` when executed on a JSON type that is not an object. + +## Examples + +??? example + + The example shows how `count()` is used. + + ```cpp + --8<-- "examples/count.cpp" + ``` + + Output: + + ```json + --8<-- "examples/count.output" + ``` + +## Version history + +1. Added in version 3.11.0. +2. Added in version 1.0.0. Changed parameter `key` type to `KeyType&&` in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/crbegin.md b/docs/mkdocs/docs/api/basic_json/crbegin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/crbegin.md rename to docs/mkdocs/docs/api/basic_json/crbegin.md diff --git a/doc/mkdocs/docs/api/basic_json/crend.md b/docs/mkdocs/docs/api/basic_json/crend.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/crend.md rename to docs/mkdocs/docs/api/basic_json/crend.md diff --git a/docs/mkdocs/docs/api/basic_json/default_object_comparator_t.md b/docs/mkdocs/docs/api/basic_json/default_object_comparator_t.md new file mode 100644 index 000000000..8a237f662 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/default_object_comparator_t.md @@ -0,0 +1,35 @@ +# nlohmann::basic_json::default_object_comparator_t + +```cpp +using default_object_comparator_t = std::less; // until C++14 + +using default_object_comparator_t = std::less<>; // since C++14 +``` + +The default comparator used by [`object_t`](object_t.md). + +Since C++14 a transparent comparator is used which prevents unnecessary string construction +when looking up a key in an object. + +The actual comparator used depends on [`object_t`](object_t.md) and can be obtained via +[`object_comparator_t`](object_comparator_t.md). + +## Examples + +??? example + + The example below demonstrates the default comparator. + + ```cpp + --8<-- "examples/default_object_comparator_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/default_object_comparator_t.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/diff.md b/docs/mkdocs/docs/api/basic_json/diff.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/diff.md rename to docs/mkdocs/docs/api/basic_json/diff.md diff --git a/doc/mkdocs/docs/api/basic_json/dump.md b/docs/mkdocs/docs/api/basic_json/dump.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/dump.md rename to docs/mkdocs/docs/api/basic_json/dump.md diff --git a/doc/mkdocs/docs/api/basic_json/emplace.md b/docs/mkdocs/docs/api/basic_json/emplace.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/emplace.md rename to docs/mkdocs/docs/api/basic_json/emplace.md diff --git a/doc/mkdocs/docs/api/basic_json/emplace_back.md b/docs/mkdocs/docs/api/basic_json/emplace_back.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/emplace_back.md rename to docs/mkdocs/docs/api/basic_json/emplace_back.md diff --git a/doc/mkdocs/docs/api/basic_json/empty.md b/docs/mkdocs/docs/api/basic_json/empty.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/empty.md rename to docs/mkdocs/docs/api/basic_json/empty.md diff --git a/doc/mkdocs/docs/api/basic_json/end.md b/docs/mkdocs/docs/api/basic_json/end.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/end.md rename to docs/mkdocs/docs/api/basic_json/end.md diff --git a/doc/mkdocs/docs/api/basic_json/erase.md b/docs/mkdocs/docs/api/basic_json/erase.md similarity index 84% rename from doc/mkdocs/docs/api/basic_json/erase.md rename to docs/mkdocs/docs/api/basic_json/erase.md index d94c25b7f..6cb749b8c 100644 --- a/doc/mkdocs/docs/api/basic_json/erase.md +++ b/docs/mkdocs/docs/api/basic_json/erase.md @@ -13,6 +13,10 @@ const_iterator erase(const_iterator first, const_iterator last); size_type erase(const typename object_t::key_type& key); // (4) +template +size_type erase(KeyType&& key); + +// (5) void erase(const size_type idx); ``` @@ -29,7 +33,17 @@ void erase(const size_type idx); 3. Removes an element from a JSON object by key. -4. Removes an element from a JSON array by index. +4. See 3. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +5. Removes an element from a JSON array by index. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). ## Parameters @@ -56,7 +70,8 @@ void erase(const size_type idx); is returned. 3. Number of elements removed. If `ObjectType` is the default `std::map` type, the return value will always be `0` (`key` was not found) or `1` (`key` was found). -4. / +4. See 3. +5. (none) ## Exception safety @@ -83,7 +98,8 @@ Strong exception safety: if an exception occurs, the original value stays intact 3. The function can throw the following exceptions: - Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than JSON object; example: `"cannot use erase() with null"` -4. The function can throw the following exceptions: +4. See 3. +5. The function can throw the following exceptions: - Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than JSON object; example: `"cannot use erase() with null"` - Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) when `idx >= size()`; example: @@ -103,14 +119,16 @@ Strong exception safety: if an exception occurs, the original value stays intact - strings and binary: linear in the length of the member - other types: constant 3. `log(size()) + count(key)` -4. Linear in distance between `idx` and the end of the container. +4. `log(size()) + count(key)` +5. Linear in distance between `idx` and the end of the container. ## Notes 1. Invalidates iterators and references at or after the point of the `erase`, including the `end()` iterator. -2. / +2. (none) 3. References and iterators to the erased elements are invalidated. Other references and iterators are not affected. -4. / +4. See 3. +5. (none) ## Examples @@ -156,7 +174,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/erase__key_type.output" ``` -??? example "Example: (4) remove element from a JSON array given an index" +??? example "Example: (5) remove element from a JSON array given an index" The example shows the effect of `erase()` using an array index. @@ -172,5 +190,8 @@ Strong exception safety: if an exception occurs, the original value stays intact ## Version history -- Added in version 1.0.0. -- Added support for binary types in version 3.8.0. +1. Added in version 1.0.0. Added support for binary types in version 3.8.0. +2. Added in version 1.0.0. Added support for binary types in version 3.8.0. +3. Added in version 1.0.0. +4. Added in version 3.11.0. +5. Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/error_handler_t.md b/docs/mkdocs/docs/api/basic_json/error_handler_t.md similarity index 62% rename from doc/mkdocs/docs/api/basic_json/error_handler_t.md rename to docs/mkdocs/docs/api/basic_json/error_handler_t.md index afd20f89d..dc32ced9b 100644 --- a/doc/mkdocs/docs/api/basic_json/error_handler_t.md +++ b/docs/mkdocs/docs/api/basic_json/error_handler_t.md @@ -20,6 +20,23 @@ replace ignore : ignore invalid UTF-8 sequences; all bytes are copied to the output unchanged +## Examples + +??? example + + The example below shows how the different values of the `error_handler_t` influence the behavior of + [`dump`](dump.md) when reading serializing an invalid UTF-8 sequence. + + ```cpp + --8<-- "examples/error_handler_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/error_handler_t.output" + ``` + ## Version history - Added in version 3.4.0. diff --git a/doc/mkdocs/docs/api/basic_json/exception.md b/docs/mkdocs/docs/api/basic_json/exception.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/exception.md rename to docs/mkdocs/docs/api/basic_json/exception.md diff --git a/docs/mkdocs/docs/api/basic_json/find.md b/docs/mkdocs/docs/api/basic_json/find.md new file mode 100644 index 000000000..d4fddc579 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/find.md @@ -0,0 +1,72 @@ +# nlohmann::basic_json::find + +```cpp +// (1) +iterator find(const typename object_t::key_type& key); +const_iterator find(const typename object_t::key_type& key) const; + +// (2) +template +iterator find(KeyType&& key); +template +const_iterator find(KeyType&& key) const; +``` + +1. Finds an element in a JSON object with a key equivalent to `key`. If the element is not found or the + JSON value is not an object, `end()` is returned. +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). + +## Parameters + +`key` (in) +: key value of the element to search for. + +## Return value + +Iterator to an element with a key equivalent to `key`. If no such element is found or the JSON value is not an object, +a past-the-end iterator (see `end()`) is returned. + +## Exception safety + +Strong exception safety: if an exception occurs, the original value stays intact. + +## Complexity + +Logarithmic in the size of the JSON object. + +## Notes + +This method always returns `end()` when executed on a JSON type that is not an object. + +## Examples + +??? example + + The example shows how `find()` is used. + + ```cpp + --8<-- "examples/find__key_type.cpp" + ``` + + Output: + + ```json + --8<-- "examples/find__key_type.output" + ``` + +## See also + +- [contains](contains.md) checks whether a key exists + +## Version history + +1. Added in version 3.11.0. +2. Added in version 1.0.0. Changed to support comparable types in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/flatten.md b/docs/mkdocs/docs/api/basic_json/flatten.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/flatten.md rename to docs/mkdocs/docs/api/basic_json/flatten.md diff --git a/docs/mkdocs/docs/api/basic_json/from_bjdata.md b/docs/mkdocs/docs/api/basic_json/from_bjdata.md new file mode 100644 index 000000000..3c5eeb351 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/from_bjdata.md @@ -0,0 +1,93 @@ +# nlohmann::basic_json::from_bjdata + +```cpp +// (1) +template +static basic_json from_bjdata(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true); +// (2) +template +static basic_json from_bjdata(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true); +``` + +Deserializes a given input to a JSON value using the BJData (Binary JData) serialization format. + +1. Reads from a compatible input. +2. Reads from an iterator range. + +The exact mapping and its limitations is described on a [dedicated page](../../features/binary_formats/bjdata.md). + +## Template parameters + +`InputType` +: A compatible input, for instance: + + - an `std::istream` object + - a `FILE` pointer + - a C-style array of characters + - a pointer to a null-terminated string of single byte characters + - an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators. + +`IteratorType` +: a compatible iterator type + +## Parameters + +`i` (in) +: an input in BJData format convertible to an input adapter + +`first` (in) +: iterator to start of the input + +`last` (in) +: iterator to end of the input + +`strict` (in) +: whether to expect the input to be consumed until EOF (`#!cpp true` by default) + +`allow_exceptions` (in) +: whether to throw exceptions in case of a parse error (optional, `#!cpp true` by default) + +## Return value + +deserialized JSON value; in case of a parse error and `allow_exceptions` set to `#!cpp false`, the return value will be +`value_t::discarded`. The latter can be checked with [`is_discarded`](is_discarded.md). + +## Exception safety + +Strong guarantee: if an exception is thrown, there are no changes in the JSON value. + +## Exceptions + +- Throws [parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely or + the end of file was not reached when `strict` was set to true +- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs +- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string could not be parsed + successfully + +## Complexity + +Linear in the size of the input. + +## Examples + +??? example + + The example shows the deserialization of a byte vector in BJData format to a JSON value. + + ```cpp + --8<-- "examples/from_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_bjdata.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/from_bson.md b/docs/mkdocs/docs/api/basic_json/from_bson.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_bson.md rename to docs/mkdocs/docs/api/basic_json/from_bson.md diff --git a/doc/mkdocs/docs/api/basic_json/from_cbor.md b/docs/mkdocs/docs/api/basic_json/from_cbor.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_cbor.md rename to docs/mkdocs/docs/api/basic_json/from_cbor.md diff --git a/doc/mkdocs/docs/api/basic_json/from_msgpack.md b/docs/mkdocs/docs/api/basic_json/from_msgpack.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_msgpack.md rename to docs/mkdocs/docs/api/basic_json/from_msgpack.md diff --git a/doc/mkdocs/docs/api/basic_json/from_ubjson.md b/docs/mkdocs/docs/api/basic_json/from_ubjson.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_ubjson.md rename to docs/mkdocs/docs/api/basic_json/from_ubjson.md diff --git a/doc/mkdocs/docs/api/basic_json/front.md b/docs/mkdocs/docs/api/basic_json/front.md similarity index 89% rename from doc/mkdocs/docs/api/basic_json/front.md rename to docs/mkdocs/docs/api/basic_json/front.md index 909f0b59b..e258c36a0 100644 --- a/doc/mkdocs/docs/api/basic_json/front.md +++ b/docs/mkdocs/docs/api/basic_json/front.md @@ -28,9 +28,9 @@ Constant. ## Notes -!!! danger +!!! info "Precondition" - Calling `front` on an empty array or object is undefined behavior and is **guarded by an assertion**! + The array or object must not be empty. Calling `front` on an empty array or object yields undefined behavior. ## Examples diff --git a/doc/mkdocs/docs/api/basic_json/get.md b/docs/mkdocs/docs/api/basic_json/get.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/get.md rename to docs/mkdocs/docs/api/basic_json/get.md index 0a0bc3bab..96fc221da 100644 --- a/doc/mkdocs/docs/api/basic_json/get.md +++ b/docs/mkdocs/docs/api/basic_json/get.md @@ -90,7 +90,7 @@ Depends on what `json_serializer` `from_json()` method throws ## Notes -!!! warning +!!! danger "Undefined behavior" Writing data to the pointee (overload 3) of the result yields an undefined state. diff --git a/docs/mkdocs/docs/api/basic_json/get_allocator.md b/docs/mkdocs/docs/api/basic_json/get_allocator.md new file mode 100644 index 000000000..07a4d8456 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/get_allocator.md @@ -0,0 +1,31 @@ +# nlohmann::basic_json::get_allocator + +```cpp +static allocator_type get_allocator(); +``` + +Returns the allocator associated with the container. + +## Return value + +associated allocator + +## Examples + +??? example + + The example shows how `get_allocator()` is used to created `json` values. + + ```cpp + --8<-- "examples/get_allocator.cpp" + ``` + + Output: + + ```json + --8<-- "examples/get_allocator.output" + ``` + +## Version history + +- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/get_binary.md b/docs/mkdocs/docs/api/basic_json/get_binary.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/get_binary.md rename to docs/mkdocs/docs/api/basic_json/get_binary.md diff --git a/doc/mkdocs/docs/api/basic_json/get_ptr.md b/docs/mkdocs/docs/api/basic_json/get_ptr.md similarity index 97% rename from doc/mkdocs/docs/api/basic_json/get_ptr.md rename to docs/mkdocs/docs/api/basic_json/get_ptr.md index 72517cd7e..2441e1156 100644 --- a/doc/mkdocs/docs/api/basic_json/get_ptr.md +++ b/docs/mkdocs/docs/api/basic_json/get_ptr.md @@ -33,7 +33,7 @@ Constant. ## Notes -!!! warning +!!! danger "Undefined behavior" Writing data to the pointee of the result yields an undefined state. diff --git a/doc/mkdocs/docs/api/basic_json/get_ref.md b/docs/mkdocs/docs/api/basic_json/get_ref.md similarity index 95% rename from doc/mkdocs/docs/api/basic_json/get_ref.md rename to docs/mkdocs/docs/api/basic_json/get_ref.md index 1140836e4..b1219742c 100644 --- a/doc/mkdocs/docs/api/basic_json/get_ref.md +++ b/docs/mkdocs/docs/api/basic_json/get_ref.md @@ -16,7 +16,7 @@ Implicit reference access to the internally stored JSON value. No copies are mad : reference type; must be a reference to [`array_t`](array_t.md), [`object_t`](object_t.md), [`string_t`](string_t.md), [`boolean_t`](boolean_t.md), [`number_integer_t`](number_integer_t.md), or [`number_unsigned_t`](number_unsigned_t.md), [`number_float_t`](number_float_t.md), or [`binary_t`](binary_t.md). - Enforced by static assertion. + Enforced by a static assertion. ## Return value @@ -38,7 +38,7 @@ Constant. ## Notes -!!! warning +!!! danger "Undefined behavior" Writing data to the referee of the result yields an undefined state. diff --git a/doc/mkdocs/docs/api/basic_json/get_to.md b/docs/mkdocs/docs/api/basic_json/get_to.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/get_to.md rename to docs/mkdocs/docs/api/basic_json/get_to.md diff --git a/doc/mkdocs/docs/api/basic_json/index.md b/docs/mkdocs/docs/api/basic_json/index.md similarity index 97% rename from doc/mkdocs/docs/api/basic_json/index.md rename to docs/mkdocs/docs/api/basic_json/index.md index f8828dbd8..2191d671f 100644 --- a/doc/mkdocs/docs/api/basic_json/index.md +++ b/docs/mkdocs/docs/api/basic_json/index.md @@ -128,6 +128,7 @@ The class satisfies the following concept requirements: - [**array_t**](array_t.md) - type for arrays - [**binary_t**](binary_t.md) - type for binary arrays - [**boolean_t**](boolean_t.md) - type for booleans +- [**default_object_comparator_t**](default_object_comparator_t.md) - default comparator for objects - [**number_float_t**](number_float_t.md) - type for numbers (floating-point) - [**number_integer_t**](number_integer_t.md) - type for numbers (integer) - [**number_unsigned_t**](number_unsigned_t.md) - type for numbers (unsigned) @@ -232,9 +233,10 @@ Access to the JSON value - [**operator==**](operator_eq.md) - comparison: equal - [**operator!=**](operator_ne.md) - comparison: not equal - [**operator<**](operator_lt.md) - comparison: less than -- [**operator<=**](operator_le.md) - comparison: less than or equal - [**operator>**](operator_gt.md) - comparison: greater than +- [**operator<=**](operator_le.md) - comparison: less than or equal - [**operator>=**](operator_ge.md) - comparison: greater than or equal +- [**operator<=>**](operator_spaceship.md) - comparison: 3-way ### Serialization / Dumping @@ -267,10 +269,12 @@ Access to the JSON value ### Binary formats +- [**from_bjdata**](from_bjdata.md) (_static_) - create a JSON value from an input in BJData format - [**from_bson**](from_bson.md) (_static_) - create a JSON value from an input in BSON format - [**from_cbor**](from_cbor.md) (_static_) - create a JSON value from an input in CBOR format - [**from_msgpack**](from_msgpack.md) (_static_) - create a JSON value from an input in MessagePack format - [**from_ubjson**](from_ubjson.md) (_static_) - create a JSON value from an input in UBJSON format +- [**to_bjdata**](to_bjdata.md) (_static_) - create a BJData serialization of a given JSON value - [**to_bson**](to_bson.md) (_static_) - create a BSON serialization of a given JSON value - [**to_cbor**](to_cbor.md) (_static_) - create a CBOR serialization of a given JSON value - [**to_msgpack**](to_msgpack.md) (_static_) - create a MessagePack serialization of a given JSON value @@ -292,7 +296,7 @@ Access to the JSON value - [**std::hash<basic_json>**](std_hash.md) - return a hash value for a JSON object - [**std::swap<basic_json>**](std_swap.md) - exchanges the values of two JSON objects -## Example +## Examples ??? example diff --git a/doc/mkdocs/docs/api/basic_json/input_format_t.md b/docs/mkdocs/docs/api/basic_json/input_format_t.md similarity index 57% rename from doc/mkdocs/docs/api/basic_json/input_format_t.md rename to docs/mkdocs/docs/api/basic_json/input_format_t.md index 4accf6dee..a3baabab8 100644 --- a/doc/mkdocs/docs/api/basic_json/input_format_t.md +++ b/docs/mkdocs/docs/api/basic_json/input_format_t.md @@ -6,7 +6,8 @@ enum class input_format_t { cbor, msgpack, ubjson, - bson + bson, + bjdata }; ``` @@ -27,6 +28,25 @@ ubjson bson : BSON (Binary JSON) +bjdata +: BJData (Binary JData) + +## Examples + +??? example + + The example below shows how an `input_format_t` enum value is passed to `sax_parse` to set the input format to CBOR. + + ```cpp + --8<-- "examples/sax_parse__binary.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse__binary.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/basic_json/insert.md b/docs/mkdocs/docs/api/basic_json/insert.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/insert.md rename to docs/mkdocs/docs/api/basic_json/insert.md index fdd8fe6b5..2e6b29301 100644 --- a/doc/mkdocs/docs/api/basic_json/insert.md +++ b/docs/mkdocs/docs/api/basic_json/insert.md @@ -50,7 +50,7 @@ void insert(const_iterator first, const_iterator last); 2. iterator pointing to the first element inserted, or `pos` if `#!cpp cnt==0` 3. iterator pointing to the first element inserted, or `pos` if `#!cpp first==last` 4. iterator pointing to the first element inserted, or `pos` if `ilist` is empty -5. / +5. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/invalid_iterator.md b/docs/mkdocs/docs/api/basic_json/invalid_iterator.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/invalid_iterator.md rename to docs/mkdocs/docs/api/basic_json/invalid_iterator.md diff --git a/doc/mkdocs/docs/api/basic_json/is_array.md b/docs/mkdocs/docs/api/basic_json/is_array.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_array.md rename to docs/mkdocs/docs/api/basic_json/is_array.md diff --git a/doc/mkdocs/docs/api/basic_json/is_binary.md b/docs/mkdocs/docs/api/basic_json/is_binary.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_binary.md rename to docs/mkdocs/docs/api/basic_json/is_binary.md diff --git a/doc/mkdocs/docs/api/basic_json/is_boolean.md b/docs/mkdocs/docs/api/basic_json/is_boolean.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_boolean.md rename to docs/mkdocs/docs/api/basic_json/is_boolean.md diff --git a/doc/mkdocs/docs/api/basic_json/is_discarded.md b/docs/mkdocs/docs/api/basic_json/is_discarded.md similarity index 95% rename from doc/mkdocs/docs/api/basic_json/is_discarded.md rename to docs/mkdocs/docs/api/basic_json/is_discarded.md index 6de31c937..663cbf889 100644 --- a/doc/mkdocs/docs/api/basic_json/is_discarded.md +++ b/docs/mkdocs/docs/api/basic_json/is_discarded.md @@ -24,7 +24,7 @@ Constant. ## Notes -!!! note +!!! note "Comparisons" Discarded values are never compared equal with [`operator==`](operator_eq.md). That is, checking whether a JSON value `j` is discarded will only work via: @@ -41,7 +41,7 @@ Constant. will always be `#!cpp false`. -!!! note +!!! note "Removal during parsing with callback functions" When a value is discarded by a callback function (see [`parser_callback_t`](parser_callback_t.md)) during parsing, then it is removed when it is part of a structured value. For instance, if the second value of an array is discarded, diff --git a/doc/mkdocs/docs/api/basic_json/is_null.md b/docs/mkdocs/docs/api/basic_json/is_null.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_null.md rename to docs/mkdocs/docs/api/basic_json/is_null.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number.md b/docs/mkdocs/docs/api/basic_json/is_number.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number.md rename to docs/mkdocs/docs/api/basic_json/is_number.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number_float.md b/docs/mkdocs/docs/api/basic_json/is_number_float.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number_float.md rename to docs/mkdocs/docs/api/basic_json/is_number_float.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number_integer.md b/docs/mkdocs/docs/api/basic_json/is_number_integer.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number_integer.md rename to docs/mkdocs/docs/api/basic_json/is_number_integer.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number_unsigned.md b/docs/mkdocs/docs/api/basic_json/is_number_unsigned.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number_unsigned.md rename to docs/mkdocs/docs/api/basic_json/is_number_unsigned.md diff --git a/doc/mkdocs/docs/api/basic_json/is_object.md b/docs/mkdocs/docs/api/basic_json/is_object.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_object.md rename to docs/mkdocs/docs/api/basic_json/is_object.md diff --git a/doc/mkdocs/docs/api/basic_json/is_primitive.md b/docs/mkdocs/docs/api/basic_json/is_primitive.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_primitive.md rename to docs/mkdocs/docs/api/basic_json/is_primitive.md diff --git a/doc/mkdocs/docs/api/basic_json/is_string.md b/docs/mkdocs/docs/api/basic_json/is_string.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_string.md rename to docs/mkdocs/docs/api/basic_json/is_string.md diff --git a/doc/mkdocs/docs/api/basic_json/is_structured.md b/docs/mkdocs/docs/api/basic_json/is_structured.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_structured.md rename to docs/mkdocs/docs/api/basic_json/is_structured.md diff --git a/doc/mkdocs/docs/api/basic_json/items.md b/docs/mkdocs/docs/api/basic_json/items.md similarity index 98% rename from doc/mkdocs/docs/api/basic_json/items.md rename to docs/mkdocs/docs/api/basic_json/items.md index b388824f9..0b34ddcba 100644 --- a/doc/mkdocs/docs/api/basic_json/items.md +++ b/docs/mkdocs/docs/api/basic_json/items.md @@ -63,7 +63,7 @@ Constant. When iterating over an array, `key()` will return the index of the element as string (see example). For primitive types (e.g., numbers), `key()` returns an empty string. -!!! warning +!!! danger "Lifetime issues" Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exceeds the iteration. See for more information. diff --git a/doc/mkdocs/docs/api/basic_json/json_serializer.md b/docs/mkdocs/docs/api/basic_json/json_serializer.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/json_serializer.md rename to docs/mkdocs/docs/api/basic_json/json_serializer.md diff --git a/doc/mkdocs/docs/api/basic_json/max_size.md b/docs/mkdocs/docs/api/basic_json/max_size.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/max_size.md rename to docs/mkdocs/docs/api/basic_json/max_size.md diff --git a/doc/mkdocs/docs/api/basic_json/merge_patch.md b/docs/mkdocs/docs/api/basic_json/merge_patch.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/merge_patch.md rename to docs/mkdocs/docs/api/basic_json/merge_patch.md diff --git a/doc/mkdocs/docs/api/basic_json/meta.md b/docs/mkdocs/docs/api/basic_json/meta.md similarity index 94% rename from doc/mkdocs/docs/api/basic_json/meta.md rename to docs/mkdocs/docs/api/basic_json/meta.md index e2b312e0c..87767e4d5 100644 --- a/doc/mkdocs/docs/api/basic_json/meta.md +++ b/docs/mkdocs/docs/api/basic_json/meta.md @@ -45,6 +45,10 @@ Constant. --8<-- "examples/meta.output" ``` +## See also + +- [**NLOHMANN_JSON_VERSION_MAJOR**/**NLOHMANN_JSON_VERSION_MINOR**/**NLOHMANN_JSON_VERSION_PATCH**](../macros/nlohmann_json_version_major.md) - library version information + ## Version history - Added in version 2.1.0. diff --git a/doc/mkdocs/docs/api/basic_json/number_float_t.md b/docs/mkdocs/docs/api/basic_json/number_float_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/number_float_t.md rename to docs/mkdocs/docs/api/basic_json/number_float_t.md diff --git a/doc/mkdocs/docs/api/basic_json/number_integer_t.md b/docs/mkdocs/docs/api/basic_json/number_integer_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/number_integer_t.md rename to docs/mkdocs/docs/api/basic_json/number_integer_t.md diff --git a/doc/mkdocs/docs/api/basic_json/number_unsigned_t.md b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/number_unsigned_t.md rename to docs/mkdocs/docs/api/basic_json/number_unsigned_t.md diff --git a/doc/mkdocs/docs/api/basic_json/object.md b/docs/mkdocs/docs/api/basic_json/object.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/object.md rename to docs/mkdocs/docs/api/basic_json/object.md diff --git a/docs/mkdocs/docs/api/basic_json/object_comparator_t.md b/docs/mkdocs/docs/api/basic_json/object_comparator_t.md new file mode 100644 index 000000000..496a56267 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/object_comparator_t.md @@ -0,0 +1,31 @@ +# nlohmann::basic_json::object_comparator_t + +```cpp +using object_comparator_t = typename object_t::key_compare; +// or +using object_comparator_t = default_object_comparator_t; +``` + +The comparator used by [`object_t`](object_t.md). Defined as `#!cpp typename object_t::key_compare` if available, +and [`default_object_comparator_t`](default_object_comparator_t.md) otherwise. + +## Examples + +??? example + + The example below demonstrates the used object comparator. + + ```cpp + --8<-- "examples/object_comparator_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/object_comparator_t.output" + ``` + +## Version history + +- Added in version 3.0.0. +- Changed to be conditionally defined as `#!cpp typename object_t::key_compare` or `default_object_comparator_t` in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/object_t.md b/docs/mkdocs/docs/api/basic_json/object_t.md similarity index 96% rename from doc/mkdocs/docs/api/basic_json/object_t.md rename to docs/mkdocs/docs/api/basic_json/object_t.md index d4bea15aa..67b3bb78c 100644 --- a/doc/mkdocs/docs/api/basic_json/object_t.md +++ b/docs/mkdocs/docs/api/basic_json/object_t.md @@ -3,7 +3,7 @@ ```cpp using object_t = ObjectType>>; ``` @@ -52,7 +52,7 @@ std::map< > ``` -See [`object_comparator_t`](object_comparator_t.md) for more information. +See [`default_object_comparator_t`](default_object_comparator_t.md) for more information. #### Behavior diff --git a/doc/mkdocs/docs/api/basic_json/operator+=.md b/docs/mkdocs/docs/api/basic_json/operator+=.md similarity index 85% rename from doc/mkdocs/docs/api/basic_json/operator+=.md rename to docs/mkdocs/docs/api/basic_json/operator+=.md index 074b30003..dc5f2ecc4 100644 --- a/doc/mkdocs/docs/api/basic_json/operator+=.md +++ b/docs/mkdocs/docs/api/basic_json/operator+=.md @@ -41,12 +41,9 @@ reference operator+=(initializer_list_t init); ## Exceptions -1. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON array or null; example: `"cannot use operator+=() with number"` -2. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON object or null; example: `"cannot use operator+=() with number"` +All functions can throw the following exception: + - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than + JSON array or null; example: `"cannot use operator+=() with number"` ## Complexity diff --git a/doc/mkdocs/docs/api/basic_json/operator=.md b/docs/mkdocs/docs/api/basic_json/operator=.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator=.md rename to docs/mkdocs/docs/api/basic_json/operator=.md diff --git a/doc/mkdocs/docs/api/basic_json/operator[].md b/docs/mkdocs/docs/api/basic_json/operator[].md similarity index 72% rename from doc/mkdocs/docs/api/basic_json/operator[].md rename to docs/mkdocs/docs/api/basic_json/operator[].md index 5b6512a21..9fa0c8999 100644 --- a/doc/mkdocs/docs/api/basic_json/operator[].md +++ b/docs/mkdocs/docs/api/basic_json/operator[].md @@ -6,26 +6,32 @@ reference operator[](size_type idx); const_reference operator[](size_type idx) const; // (2) -reference operator[](const typename object_t::key_type& key); +reference operator[](typename object_t::key_type key); const_reference operator[](const typename object_t::key_type& key) const; -template -reference operator[](T* key); -template -const_reference operator[](T* key) const; // (3) +template +reference operator[](KeyType&& key); +template +const_reference operator[](KeyType&& key) const; + +// (4) reference operator[](const json_pointer& ptr); const_reference operator[](const json_pointer& ptr) const; ``` 1. Returns a reference to the array element at specified location `idx`. -2. Returns a reference to the object element at with specified key `key`. -3. Returns a reference to the element at with specified JSON pointer `ptr`. +2. Returns a reference to the object element with specified key `key`. The non-const qualified overload takes the key by value. +3. See 2. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. +4. Returns a reference to the element with specified JSON pointer `ptr`. ## Template parameters -`T` -: string literal convertible to `object_t::key_type` +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). ## Parameters @@ -40,9 +46,10 @@ const_reference operator[](const json_pointer& ptr) const; ## Return value -1. reference to the element at index `idx` -2. reference to the element at key `key` -3. reference to the element pointed to by `ptr` +1. (const) reference to the element at index `idx` +2. (const) reference to the element at key `key` +3. (const) reference to the element at key `key` +4. (const) reference to the element pointed to by `ptr` ## Exception safety @@ -56,7 +63,8 @@ Strong exception safety: if an exception occurs, the original value stays intact 2. The function can throw the following exceptions: - Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the JSON value is not an object or null; in that case, using the `[]` operator with a key makes no sense. -3. The function can throw the following exceptions: +3. See 2. +4. The function can throw the following exceptions: - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in the passed JSON pointer `ptr` begins with '0'. - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed @@ -70,14 +78,16 @@ Strong exception safety: if an exception occurs, the original value stays intact 1. Constant if `idx` is in the range of the array. Otherwise, linear in `idx - size()`. 2. Logarithmic in the size of the container. -3. Constant +3. Logarithmic in the size of the container. +4. Logarithmic in the size of the container. ## Notes -!!! danger +!!! danger "Undefined behavior and runtime assertions" 1. If the element with key `idx` does not exist, the behavior is undefined. - 2. If the element with key `key` does not exist, the behavior is undefined and is **guarded by an assertion**! + 2. If the element with key `key` does not exist, the behavior is undefined and is **guarded by a + [runtime assertion](../../features/assertions.md)**! 1. The non-const version may add values: If `idx` is beyond the range of the array (i.e., `idx >= size()`), then the array is silently filled up with `#!json null` values to make `idx` a valid reference to the last stored element. In @@ -86,7 +96,9 @@ Strong exception safety: if an exception occurs, the original value stays intact 2. If `key` is not found in the object, then it is silently added to the object and filled with a `#!json null` value to make `key` a valid reference. In case the value was `#!json null` before, it is converted to an object. -3. `null` values are created in arrays and objects if necessary. +3. See 2. + +4. `null` values are created in arrays and objects if necessary. In particular: @@ -142,7 +154,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/operatorarray__key_type.output" ``` -??? example "Example (2): access specified object element" +??? example "Example (2): access specified object element (const)" The example below shows how object elements can be read using the `[]` operator. @@ -156,7 +168,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/operatorarray__key_type_const.output" ``` -??? example "Example (3): access specified element via JSON Pointer" +??? example "Example (4): access specified element via JSON Pointer" The example below shows how values can be read and written using JSON Pointers. @@ -170,7 +182,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/operatorjson_pointer.output" ``` -??? example "Example (3): access specified element via JSON Pointer" +??? example "Example (4): access specified element via JSON Pointer (const)" The example below shows how values can be read using JSON Pointers. @@ -186,11 +198,14 @@ Strong exception safety: if an exception occurs, the original value stays intact ## See also +- documentation on [unchecked access](../../features/element_access/unchecked_access.md) +- documentation on [runtime assertions](../../features/assertions.md) - see [`at`](at.md) for access by reference with range checking - see [`value`](value.md) for access with default value ## Version history 1. Added in version 1.0.0. -2. Added in version 1.0.0. Overloads for `T* key` added in version 1.1.0. -3. Added in version 2.0.0. +2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3) in version 3.11.0. +3. Added in version 3.11.0. +4. Added in version 2.0.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_ValueType.md b/docs/mkdocs/docs/api/basic_json/operator_ValueType.md new file mode 100644 index 000000000..7c1901668 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_ValueType.md @@ -0,0 +1,82 @@ +# nlohmann::basic_json::operator ValueType + +```cpp +template +JSON_EXPLICIT operator ValueType() const; +``` + +Implicit type conversion between the JSON value and a compatible value. The call is realized by calling +[`get()`](get.md). See [Notes](#notes) for the meaning of `JSON_EXPLICIT`. + +## Template parameters + +`ValueType` +: the value type to return + +## Return value + +copy of the JSON value, converted to `ValueType` + +## Exceptions + +Depends on what `json_serializer` `from_json()` method throws + +## Complexity + +Linear in the size of the JSON value. + +## Notes + +!!! note "Definition of `JSON_EXPLICIT`" + + By default `JSON_EXPLICIT` is defined to the empty string, so the signature is: + + ```cpp + template + operator ValueType() const; + ``` + + If [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) is set to `0`, + `JSON_EXPLICIT` is defined to `#!cpp explicit`: + + ```cpp + template + explicit operator ValueType() const; + ``` + + That is, implicit conversions can be switched off by defining + [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) to `0`. + +!!! info "Future behavior change" + + Implicit conversions will be switched off by default in the next major release of the library. That is, + `JSON_EXPLICIT` will be set to `#!cpp explicit` by default. + + You can prepare existing code by already defining + [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) to `0` and replace any implicit + conversions with calls to [`get`](../basic_json/get.md). + +## Examples + +??? example + + The example below shows several conversions from JSON values to other types. There are a few things to note: (1) + Floating-point numbers can be converted to integers, (2) A JSON array can be converted to a standard + `std::vector`, (3) A JSON object can be converted to C++ associative containers such as + `std::unordered_map`. + + ```cpp + --8<-- "examples/operator__ValueType.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__ValueType.output" + ``` + +## Version history + +- Since version 1.0.0. +- Macros `JSON_EXPLICIT`/[`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) added + in version 3.9.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_eq.md b/docs/mkdocs/docs/api/basic_json/operator_eq.md similarity index 65% rename from doc/mkdocs/docs/api/basic_json/operator_eq.md rename to docs/mkdocs/docs/api/basic_json/operator_eq.md index 49f96b1c0..6c86bf13e 100644 --- a/doc/mkdocs/docs/api/basic_json/operator_eq.md +++ b/docs/mkdocs/docs/api/basic_json/operator_eq.md @@ -1,21 +1,31 @@ # nlohmann::basic_json::operator== ```cpp -bool operator==(const_reference lhs, const_reference rhs) noexcept; +// until C++20 +bool operator==(const_reference lhs, const_reference rhs) noexcept; // (1) template -bool operator==(const_reference lhs, const ScalarType rhs) noexcept; +bool operator==(const_reference lhs, const ScalarType rhs) noexcept; // (2) template -bool operator==(ScalarType lhs, const const_reference rhs) noexcept; +bool operator==(ScalarType lhs, const const_reference rhs) noexcept; // (2) + +// since C++20 +class basic_json { + bool operator==(const_reference rhs) const noexcept; // (1) + + template + bool operator==(ScalarType rhs) const noexcept; // (2) +}; ``` -Compares two JSON values for equality according to the following rules: +1. Compares two JSON values for equality according to the following rules: + - Two JSON values are equal if (1) neither value is discarded, or (2) they are of the same + type and their stored values are the same according to their respective `operator==`. + - Integer and floating-point numbers are automatically converted before comparison. -- Two JSON values are equal if (1) they are not discarded, (2) they are from the same type, and (3) their stored values - are the same according to their respective `operator==`. -- Integer and floating-point numbers are automatically converted before comparison. Note that two NaN values are always - treated as unequal. +2. Compares a JSON value and a scalar or a scalar and a JSON value for equality by converting the + scalar to a JSON value and comparing both JSON values according to 1. ## Template parameters @@ -32,7 +42,7 @@ Compares two JSON values for equality according to the following rules: ## Return value -whether the values `lhs` and `rhs` are equal +whether the values `lhs`/`*this` and `rhs` are equal ## Exception safety @@ -44,13 +54,17 @@ Linear. ## Notes -!!! note +!!! note "Comparing special values" - - NaN values never compare equal to themselves or to other NaN values. + - `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. - JSON `#!cpp null` values are all equal. - Discarded values never compare equal to themselves. -!!! note +!!! note "Comparing floating-point numbers" Floating-point numbers inside JSON values numbers are compared with `json::number_float_t::operator==` which is `double::operator==` by default. To compare floating-point while respecting an epsilon, an alternative @@ -117,4 +131,5 @@ Linear. ## Version history -- Added in version 1.0.0. +1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. +2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_ge.md b/docs/mkdocs/docs/api/basic_json/operator_ge.md new file mode 100644 index 000000000..6730f6809 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_ge.md @@ -0,0 +1,87 @@ +# nlohmann::basic_json::operator>= + +```cpp +// until C++20 +bool operator>=(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator>=(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator>=(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is greater than or equal to another JSON value `rhs` + according to the following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(lhs < rhs)`. + +2. Compares wether a JSON value is greater than or equal to a scalar or a scalar is greater than or + equal to a JSON value by converting the scalar to a JSON value and comparing both JSON values + according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is less than or equal to `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__greaterequal.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__greaterequal.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_gt.md b/docs/mkdocs/docs/api/basic_json/operator_gt.md new file mode 100644 index 000000000..540e6076d --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_gt.md @@ -0,0 +1,86 @@ +# nlohmann::basic_json::operator> + +```cpp +// until C++20 +bool operator>(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator>(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator>(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is greater than another JSON value `rhs` according to the + following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(lhs <= rhs)`. + +2. Compares wether a JSON value is greater than a scalar or a scalar is greater than a JSON value by + converting the scalar to a JSON value and comparing both JSON values according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is greater than `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__greater.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__greater.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_gtgt.md b/docs/mkdocs/docs/api/basic_json/operator_gtgt.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_gtgt.md rename to docs/mkdocs/docs/api/basic_json/operator_gtgt.md diff --git a/docs/mkdocs/docs/api/basic_json/operator_le.md b/docs/mkdocs/docs/api/basic_json/operator_le.md new file mode 100644 index 000000000..c0f90acb2 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_le.md @@ -0,0 +1,87 @@ +# nlohmann::basic_json::operator<= + +```cpp +// until C++20 +bool operator<=(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator<=(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator<=(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is less than or equal to another JSON value `rhs` + according to the following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(rhs < lhs)`. + +1. Compares wether a JSON value is less than or equal to a scalar or a scalar is less than or equal + to a JSON value by converting the scalar to a JSON value and comparing both JSON values according + to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is less than or equal to `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__lessequal.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__lessequal.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_literal_json.md b/docs/mkdocs/docs/api/basic_json/operator_literal_json.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_literal_json.md rename to docs/mkdocs/docs/api/basic_json/operator_literal_json.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md b/docs/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md rename to docs/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md diff --git a/docs/mkdocs/docs/api/basic_json/operator_lt.md b/docs/mkdocs/docs/api/basic_json/operator_lt.md new file mode 100644 index 000000000..b5d191ec4 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_lt.md @@ -0,0 +1,96 @@ +# nlohmann::basic_json::operator< + +```cpp +// until C++20 +bool operator<(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator<(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator<(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is less than another JSON value `rhs` according to the + following rules: + - If either operand is discarded, the comparison yields `#!cpp false`. + - If both operands have the same type, the values are compared using their respective `operator<`. + - Integer and floating-point numbers are automatically converted before comparison. + - In case `lhs` and `rhs` have different types, the values are ignored and the order of the types + is considered, which is: + 1. null + 2. boolean + 3. number (all types) + 4. object + 5. array + 6. string + 7. binary + For instance, any boolean value is considered less than any string. + +2. Compares wether a JSON value is less than a scalar or a scalar is less than a JSON value by converting + the scalar to a JSON value and comparing both JSON values according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is less than `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__less.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__less.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ltlt.md b/docs/mkdocs/docs/api/basic_json/operator_ltlt.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_ltlt.md rename to docs/mkdocs/docs/api/basic_json/operator_ltlt.md diff --git a/docs/mkdocs/docs/api/basic_json/operator_ne.md b/docs/mkdocs/docs/api/basic_json/operator_ne.md new file mode 100644 index 000000000..f5d989b50 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_ne.md @@ -0,0 +1,99 @@ +# nlohmann::basic_json::operator!= + +```cpp +// until C++20 +bool operator!=(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator!=(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator!=(ScalarType lhs, const const_reference rhs) noexcept; // (2) + +// since C++20 +class basic_json { + bool operator!=(const_reference rhs) const noexcept; // (1) + + template + bool operator!=(ScalarType rhs) const noexcept; // (2) +}; +``` + +1. Compares two JSON values for inequality according to the following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(lhs == rhs)` (until C++20) or + `#!cpp !(*this == rhs)` (since C++20). + +2. Compares a JSON value and a scalar or a scalar and a JSON value for inequality by converting the + scalar to a JSON value and comparing both JSON values according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether the values `lhs`/`*this` and `rhs` are not equal + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__notequal.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__notequal.output" + ``` + +??? example + + The example demonstrates comparing several JSON types against the null pointer (JSON `#!json null`). + + ```cpp + --8<-- "examples/operator__notequal__nullptr_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__notequal__nullptr_t.output" + ``` + +## Version history + +1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. +2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_spaceship.md b/docs/mkdocs/docs/api/basic_json/operator_spaceship.md new file mode 100644 index 000000000..4beba4f86 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_spaceship.md @@ -0,0 +1,70 @@ +# nlohmann::basic_json::operator<=> + +```cpp +// since C++20 +class basic_json { + std::partial_ordering operator<=>(const_reference rhs) const noexcept; // (1) + + template + std::partial_ordering operator<=>(const ScalarType rhs) const noexcept; // (2) +}; +``` + +1. 3-way compares two JSON values producing a result of type `std::partial_ordering` according to the following rules: + - Two JSON values compare with a result of `std::partial_ordering::unordered` if either value is discarded. + - If both JSON values are of the same type, the result is produced by 3-way comparing their stored values using their + respective `operator<=>`. + - Integer and floating-point numbers are converted to their common type and then 3-way compared using their respective + `operator<=>`. + For instance, comparing an integer and a floating-point value will 3-way compare the first value convertered to + floating-point with the second value. + - Otherwise, yields a result by comparing the type (see [`value_t`](value_t.md)). + +2. 3-way compares a JSON value and a scalar or a scalar and a JSON value by converting the scalar to a JSON value and 3-way + comparing both JSON values (see 1). + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`rhs` (in) +: second value to consider + +## Return value + +the `std::partial_ordering` of the 3-way comparison of `*this` and `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + - `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `std::partial_ordering::unordered`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +## See also + +- [**operator==**](operator_eq.md) - comparison: equal +- [**operator!=**](operator_ne.md) - comparison: not equal +- [**operator<**](operator_lt.md) - comparison: less than +- [**operator<=**](operator_le.md) - comparison: less than or equal +- [**operator>**](operator_gt.md) - comparison: greater than +- [**operator>=**](operator_ge.md) - comparison: greater than or equal + +## Version history + +1. Added in version 3.11.0. +2. Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_value_t.md b/docs/mkdocs/docs/api/basic_json/operator_value_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_value_t.md rename to docs/mkdocs/docs/api/basic_json/operator_value_t.md diff --git a/doc/mkdocs/docs/api/basic_json/other_error.md b/docs/mkdocs/docs/api/basic_json/other_error.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/other_error.md rename to docs/mkdocs/docs/api/basic_json/other_error.md diff --git a/doc/mkdocs/docs/api/basic_json/out_of_range.md b/docs/mkdocs/docs/api/basic_json/out_of_range.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/out_of_range.md rename to docs/mkdocs/docs/api/basic_json/out_of_range.md diff --git a/doc/mkdocs/docs/api/basic_json/parse.md b/docs/mkdocs/docs/api/basic_json/parse.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/parse.md rename to docs/mkdocs/docs/api/basic_json/parse.md diff --git a/doc/mkdocs/docs/api/basic_json/parse_error.md b/docs/mkdocs/docs/api/basic_json/parse_error.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/parse_error.md rename to docs/mkdocs/docs/api/basic_json/parse_error.md diff --git a/doc/mkdocs/docs/api/basic_json/parse_event_t.md b/docs/mkdocs/docs/api/basic_json/parse_event_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/parse_event_t.md rename to docs/mkdocs/docs/api/basic_json/parse_event_t.md diff --git a/doc/mkdocs/docs/api/basic_json/parser_callback_t.md b/docs/mkdocs/docs/api/basic_json/parser_callback_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/parser_callback_t.md rename to docs/mkdocs/docs/api/basic_json/parser_callback_t.md diff --git a/doc/mkdocs/docs/api/basic_json/patch.md b/docs/mkdocs/docs/api/basic_json/patch.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/patch.md rename to docs/mkdocs/docs/api/basic_json/patch.md diff --git a/doc/mkdocs/docs/api/basic_json/push_back.md b/docs/mkdocs/docs/api/basic_json/push_back.md similarity index 84% rename from doc/mkdocs/docs/api/basic_json/push_back.md rename to docs/mkdocs/docs/api/basic_json/push_back.md index 60bfed305..5c7d20dd6 100644 --- a/doc/mkdocs/docs/api/basic_json/push_back.md +++ b/docs/mkdocs/docs/api/basic_json/push_back.md @@ -37,12 +37,9 @@ void push_back(initializer_list_t init); ## Exceptions -1. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON array or null; example: `"cannot use push_back() with number"` -2. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON object or null; example: `"cannot use push_back() with number"` +All functions can throw the following exception: + - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than + JSON array or null; example: `"cannot use push_back() with number"` ## Complexity diff --git a/doc/mkdocs/docs/api/basic_json/rbegin.md b/docs/mkdocs/docs/api/basic_json/rbegin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/rbegin.md rename to docs/mkdocs/docs/api/basic_json/rbegin.md diff --git a/doc/mkdocs/docs/api/basic_json/rend.md b/docs/mkdocs/docs/api/basic_json/rend.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/rend.md rename to docs/mkdocs/docs/api/basic_json/rend.md diff --git a/doc/mkdocs/docs/api/basic_json/sax_parse.md b/docs/mkdocs/docs/api/basic_json/sax_parse.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/sax_parse.md rename to docs/mkdocs/docs/api/basic_json/sax_parse.md diff --git a/doc/mkdocs/docs/api/basic_json/size.md b/docs/mkdocs/docs/api/basic_json/size.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/size.md rename to docs/mkdocs/docs/api/basic_json/size.md diff --git a/doc/mkdocs/docs/api/basic_json/std_hash.md b/docs/mkdocs/docs/api/basic_json/std_hash.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/std_hash.md rename to docs/mkdocs/docs/api/basic_json/std_hash.md diff --git a/doc/mkdocs/docs/api/basic_json/std_swap.md b/docs/mkdocs/docs/api/basic_json/std_swap.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/std_swap.md rename to docs/mkdocs/docs/api/basic_json/std_swap.md diff --git a/doc/mkdocs/docs/api/basic_json/string_t.md b/docs/mkdocs/docs/api/basic_json/string_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/string_t.md rename to docs/mkdocs/docs/api/basic_json/string_t.md diff --git a/doc/mkdocs/docs/api/basic_json/swap.md b/docs/mkdocs/docs/api/basic_json/swap.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/swap.md rename to docs/mkdocs/docs/api/basic_json/swap.md diff --git a/docs/mkdocs/docs/api/basic_json/to_bjdata.md b/docs/mkdocs/docs/api/basic_json/to_bjdata.md new file mode 100644 index 000000000..1ea850523 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/to_bjdata.md @@ -0,0 +1,70 @@ +# nlohmann::basic_json::to_bjdata + +```cpp +// (1) +static std::vector to_bjdata(const basic_json& j, + const bool use_size = false, + const bool use_type = false); + +// (2) +static void to_bjdata(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false); +static void to_bjdata(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false); +``` + +Serializes a given JSON value `j` to a byte vector using the BJData (Binary JData) serialization format. BJData +aims to be more compact than JSON itself, yet more efficient to parse. + +1. Returns a byte vector containing the BJData serialization. +2. Writes the BJData serialization to an output adapter. + +The exact mapping and its limitations is described on a [dedicated page](../../features/binary_formats/bjdata.md). + +## Parameters + +`j` (in) +: JSON value to serialize + +`o` (in) +: output adapter to write serialization to + +`use_size` (in) +: whether to add size annotations to container types; optional, `#!cpp false` by default. + +`use_type` (in) +: whether to add type annotations to container types (must be combined with `#!cpp use_size = true`); optional, +`#!cpp false` by default. + +## Return value + +1. BJData serialization as byte vector +2. (none) + +## Exception safety + +Strong guarantee: if an exception is thrown, there are no changes in the JSON value. + +## Complexity + +Linear in the size of the JSON value `j`. + +## Examples + +??? example + + The example shows the serialization of a JSON value to a byte vector in BJData format. + + ```cpp + --8<-- "examples/to_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/to_bjdata.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/to_bson.md b/docs/mkdocs/docs/api/basic_json/to_bson.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_bson.md rename to docs/mkdocs/docs/api/basic_json/to_bson.md index 664dd0e20..5c4324a3f 100644 --- a/doc/mkdocs/docs/api/basic_json/to_bson.md +++ b/docs/mkdocs/docs/api/basic_json/to_bson.md @@ -28,7 +28,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. BSON serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/to_cbor.md b/docs/mkdocs/docs/api/basic_json/to_cbor.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_cbor.md rename to docs/mkdocs/docs/api/basic_json/to_cbor.md index 05d85ed85..0f944c481 100644 --- a/doc/mkdocs/docs/api/basic_json/to_cbor.md +++ b/docs/mkdocs/docs/api/basic_json/to_cbor.md @@ -29,7 +29,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. CBOR serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/to_msgpack.md b/docs/mkdocs/docs/api/basic_json/to_msgpack.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_msgpack.md rename to docs/mkdocs/docs/api/basic_json/to_msgpack.md index fb4b40bd0..7d40981d5 100644 --- a/doc/mkdocs/docs/api/basic_json/to_msgpack.md +++ b/docs/mkdocs/docs/api/basic_json/to_msgpack.md @@ -28,7 +28,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. MessagePack serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/to_string.md b/docs/mkdocs/docs/api/basic_json/to_string.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/to_string.md rename to docs/mkdocs/docs/api/basic_json/to_string.md diff --git a/doc/mkdocs/docs/api/basic_json/to_ubjson.md b/docs/mkdocs/docs/api/basic_json/to_ubjson.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_ubjson.md rename to docs/mkdocs/docs/api/basic_json/to_ubjson.md index 0a3d87e54..e3cd5d62b 100644 --- a/doc/mkdocs/docs/api/basic_json/to_ubjson.md +++ b/docs/mkdocs/docs/api/basic_json/to_ubjson.md @@ -39,7 +39,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. UBJSON serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/type.md b/docs/mkdocs/docs/api/basic_json/type.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/type.md rename to docs/mkdocs/docs/api/basic_json/type.md diff --git a/doc/mkdocs/docs/api/basic_json/type_error.md b/docs/mkdocs/docs/api/basic_json/type_error.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/type_error.md rename to docs/mkdocs/docs/api/basic_json/type_error.md diff --git a/doc/mkdocs/docs/api/basic_json/type_name.md b/docs/mkdocs/docs/api/basic_json/type_name.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/type_name.md rename to docs/mkdocs/docs/api/basic_json/type_name.md diff --git a/doc/mkdocs/docs/api/basic_json/unflatten.md b/docs/mkdocs/docs/api/basic_json/unflatten.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/unflatten.md rename to docs/mkdocs/docs/api/basic_json/unflatten.md diff --git a/doc/mkdocs/docs/api/basic_json/update.md b/docs/mkdocs/docs/api/basic_json/update.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/update.md rename to docs/mkdocs/docs/api/basic_json/update.md diff --git a/doc/mkdocs/docs/api/basic_json/value.md b/docs/mkdocs/docs/api/basic_json/value.md similarity index 73% rename from doc/mkdocs/docs/api/basic_json/value.md rename to docs/mkdocs/docs/api/basic_json/value.md index 0b4f1cc19..6a1f3481d 100644 --- a/doc/mkdocs/docs/api/basic_json/value.md +++ b/docs/mkdocs/docs/api/basic_json/value.md @@ -4,9 +4,14 @@ // (1) template ValueType value(const typename object_t::key_type& key, - const ValueType& default_value) const; + ValueType&& default_value) const; // (2) +template +ValueType value(KeyType&& key, + ValueType&& default_value) const; + +// (3) template ValueType value(const json_pointer& ptr, const ValueType& default_value) const; @@ -24,7 +29,10 @@ ValueType value(const json_pointer& ptr, } ``` -2. Returns either a copy of an object's element at the specified JSON pointer `ptr` or a given default value if no value +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +3. Returns either a copy of an object's element at the specified JSON pointer `ptr` or a given default value if no value at `ptr` exists. The function is basically equivalent to executing @@ -36,7 +44,7 @@ ValueType value(const json_pointer& ptr, } ``` -!!! note +!!! note "Differences to `at` and `operator[]`" - Unlike [`at`](at.md), this function does not throw if the given `key`/`ptr` was not found. - Unlike [`operator[]`](operator[].md), this function does not implicitly add an element to the position defined by @@ -44,6 +52,10 @@ ValueType value(const json_pointer& ptr, ## Template parameters +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). `ValueType` : type compatible to JSON values, for instance `#!cpp int` for JSON integer numbers, `#!cpp bool` for JSON booleans, or `#!cpp std::vector` types for JSON arrays. Note the type of the expected value at `key`/`ptr` and the default @@ -55,7 +67,7 @@ ValueType value(const json_pointer& ptr, : key of the element to access `default_value` (in) -: the value to return if key/ptr found no value +: the value to return if `key`/`ptr` found no value `ptr` (in) : a JSON pointer to the element to access @@ -63,7 +75,8 @@ ValueType value(const json_pointer& ptr, ## Return value 1. copy of the element at key `key` or `default_value` if `key` is not found -1. copy of the element at JSON Pointer `ptr` or `default_value` if no value for `ptr` is found +2. copy of the element at key `key` or `default_value` if `key` is not found +3. copy of the element at JSON Pointer `ptr` or `default_value` if no value for `ptr` is found ## Exception safety @@ -77,7 +90,8 @@ changes to any JSON value. the type of the value at `key` - Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an object; in that case, using `value()` with a key makes no sense. -2. The function can throw the following exceptions: +2. See 1. +3. The function can throw the following exceptions: - Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `default_value` does not match the type of the value at `ptr` - Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an object; @@ -87,6 +101,7 @@ changes to any JSON value. 1. Logarithmic in the size of the container. 2. Logarithmic in the size of the container. +3. Logarithmic in the size of the container. ## Examples @@ -104,7 +119,7 @@ changes to any JSON value. --8<-- "examples/basic_json__value.output" ``` -??? example "Example (2): access specified object element via JSON Pointer with default value" +??? example "Example (3): access specified object element via JSON Pointer with default value" The example below shows how object elements can be queried with a default value. @@ -125,5 +140,6 @@ changes to any JSON value. ## Version history -1. Added in version 1.0.0. -2. Added in version 2.0.2. +1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0. +2. Added in version 3.11.0. +3. Added in version 2.0.2. diff --git a/docs/mkdocs/docs/api/basic_json/value_t.md b/docs/mkdocs/docs/api/basic_json/value_t.md new file mode 100644 index 000000000..f83574083 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/value_t.md @@ -0,0 +1,83 @@ +# nlohmann::basic_json::value_t + +```cpp +enum class value_t : std::uint8_t { + null, + object, + array, + string, + boolean, + number_integer, + number_unsigned, + number_float, + binary, + discarded +}; +``` + +This enumeration collects the different JSON types. It is internally used to distinguish the stored values, and the +functions [`is_null`](is_null.md), [`is_object`](is_object.md), [`is_array`](is_array.md), [`is_string`](is_string.md), +[`is_boolean`](is_boolean.md), [`is_number`](is_number.md) (with [`is_number_integer`](is_number_integer.md), +[`is_number_unsigned`](is_number_unsigned.md), and [`is_number_float`](is_number_float.md)), +[`is_discarded`](is_discarded.md), [`is_binary`](is_binary.md), [`is_primitive`](is_primitive.md), and +[`is_structured`](is_structured.md) rely on it. + +## Notes + +!!! note "Ordering" + + The order of types is as follows: + + 1. `null` + 2. `boolean` + 3. `number_integer`, `number_unsigned`, `number_float` + 4. `object` + 5. `array` + 6. `string` + 7. `binary` + + `discarded` is unordered. + +!!! note "Types of numbers" + + There are three enumerators for numbers (`number_integer`, `number_unsigned`, and `number_float`) to distinguish + between different types of numbers: + + - [`number_unsigned_t`](number_unsigned_t.md) for unsigned integers + - [`number_integer_t`](number_integer_t.md) for signed integers + - [`number_float_t`](number_float_t.md) for floating-point numbers or to approximate integers which do not fit + into the limits of their respective type + +!!! warning "Comparison operators" + + `operator<` and `operator<=>` (since C++20) are overloaded and compare according to the ordering described above. + Until C++20 all other relational and equality operators yield results according to the integer value of each + enumerator. + Since C++20 some compilers consider the _rewritten candidates_ generated from `operator<=>` during overload + resolution, while others do not. + For predictable and portable behavior use: + + - `operator<` or `operator<=>` when wanting to compare according to the order described above + - `operator==` or `operator!=` when wanting to compare according to each enumerators integer value + +## Examples + +??? example + + The following code how `type()` queries the `value_t` for all JSON types. + + ```cpp + --8<-- "examples/type.cpp" + ``` + + Output: + + ```json + --8<-- "examples/type.output" + ``` + +## Version history + +- Added in version 1.0.0. +- Added unsigned integer type in version 2.0.0. +- Added binary type in version 3.8.0. diff --git a/doc/mkdocs/docs/api/basic_json/~basic_json.md b/docs/mkdocs/docs/api/basic_json/~basic_json.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/~basic_json.md rename to docs/mkdocs/docs/api/basic_json/~basic_json.md diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md similarity index 67% rename from doc/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md index caa273df5..9913a9b5c 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md @@ -25,6 +25,22 @@ byte_container_with_subtype(container_type&& container, subtype_type subtype); `subtype` (in) : subtype +## Examples + +??? example + + The example below demonstrates how byte containers can be created. + + ```cpp + --8<-- "examples/byte_container_with_subtype__byte_container_with_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__byte_container_with_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md similarity index 59% rename from doc/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md index 56f8ee0c1..c62dead36 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md @@ -15,6 +15,22 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how `clear_subtype` can remove subtypes. + + ```cpp + --8<-- "examples/byte_container_with_subtype__clear_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__clear_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md similarity index 53% rename from doc/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md index 2fe418132..e06286e29 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md @@ -18,6 +18,22 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how `has_subtype` can check whether a subtype was set. + + ```cpp + --8<-- "examples/byte_container_with_subtype__has_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__has_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/index.md b/docs/mkdocs/docs/api/byte_container_with_subtype/index.md similarity index 100% rename from doc/mkdocs/docs/api/byte_container_with_subtype/index.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/index.md diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md similarity index 60% rename from doc/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md index 40cc2722f..cf21732b8 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md @@ -20,6 +20,22 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how a subtype can be set with `set_subtype`. + + ```cpp + --8<-- "examples/byte_container_with_subtype__set_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__set_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/subtype.md similarity index 63% rename from doc/mkdocs/docs/api/byte_container_with_subtype/subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/subtype.md index e78654b37..389241a79 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/subtype.md @@ -19,6 +19,23 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how the subtype can be retrieved with `subtype`. Note how `subtype_type(-1)` is + returned for container `c1`. + + ```cpp + --8<-- "examples/byte_container_with_subtype__subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__subtype.output" + ``` + ## Version history - Added in version 3.8.0 diff --git a/doc/mkdocs/docs/api/json.md b/docs/mkdocs/docs/api/json.md similarity index 51% rename from doc/mkdocs/docs/api/json.md rename to docs/mkdocs/docs/api/json.md index 48d344183..36edcc2c1 100644 --- a/doc/mkdocs/docs/api/json.md +++ b/docs/mkdocs/docs/api/json.md @@ -7,6 +7,22 @@ using json = basic_json<>; This type is the default specialization of the [basic_json](basic_json/index.md) class which uses the standard template types. +## Examples + +??? example + + The example below demonstrates how to use the type `nlohmann::json`. + + ```cpp + --8<-- "examples/README.cpp" + ``` + + Output: + + ```json + --8<-- "examples/README.output" + ``` + ## Version history Since version 1.0.0. diff --git a/doc/mkdocs/docs/api/json_pointer/back.md b/docs/mkdocs/docs/api/json_pointer/back.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/back.md rename to docs/mkdocs/docs/api/json_pointer/back.md diff --git a/doc/mkdocs/docs/api/json_pointer/empty.md b/docs/mkdocs/docs/api/json_pointer/empty.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/empty.md rename to docs/mkdocs/docs/api/json_pointer/empty.md diff --git a/doc/mkdocs/docs/api/json_pointer/index.md b/docs/mkdocs/docs/api/json_pointer/index.md similarity index 83% rename from doc/mkdocs/docs/api/json_pointer/index.md rename to docs/mkdocs/docs/api/json_pointer/index.md index 3504c9ff7..dc07d89b3 100644 --- a/doc/mkdocs/docs/api/json_pointer/index.md +++ b/docs/mkdocs/docs/api/json_pointer/index.md @@ -14,9 +14,15 @@ are the base for JSON patches. `RefStringType` : the string type used for the reference tokens making up the JSON pointer -## Notes +!!! warning "Deprecation" -For backwards compatibility `RefStringType` may also be a specialization of [`basic_json`](../basic_json/index.md) in which case `string_t` will be deduced as [`basic_json::string_t`](../basic_json/string_t.md). This feature is deprecated and may be removed in a future major version. + For backwards compatibility `RefStringType` may also be a specialization of [`basic_json`](../basic_json/index.md) + in which case `string_t` will be deduced as [`basic_json::string_t`](../basic_json/string_t.md). This feature is + deprecated and may be removed in a future major version. + +## Member types + +- [**string_t**](string_t.md) - the string type used for the reference tokens ## Member functions @@ -31,10 +37,6 @@ For backwards compatibility `RefStringType` may also be a specialization of [`ba - [**push_back**](push_back.md) - append an unescaped token at the end of the pointer - [**empty**](empty.md) - return whether pointer points to the root document -## Member types - -- [**string_t**](string_t.md) - the string type used for the reference tokens - ## See also - [operator""_json_pointer](../basic_json/operator_literal_json_pointer.md) - user-defined string literal for JSON pointers diff --git a/doc/mkdocs/docs/api/json_pointer/json_pointer.md b/docs/mkdocs/docs/api/json_pointer/json_pointer.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/json_pointer.md rename to docs/mkdocs/docs/api/json_pointer/json_pointer.md diff --git a/doc/mkdocs/docs/api/json_pointer/operator_slash.md b/docs/mkdocs/docs/api/json_pointer/operator_slash.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/operator_slash.md rename to docs/mkdocs/docs/api/json_pointer/operator_slash.md diff --git a/doc/mkdocs/docs/api/json_pointer/operator_slasheq.md b/docs/mkdocs/docs/api/json_pointer/operator_slasheq.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/operator_slasheq.md rename to docs/mkdocs/docs/api/json_pointer/operator_slasheq.md diff --git a/doc/mkdocs/docs/api/json_pointer/operator_string.md b/docs/mkdocs/docs/api/json_pointer/operator_string.md similarity index 57% rename from doc/mkdocs/docs/api/json_pointer/operator_string.md rename to docs/mkdocs/docs/api/json_pointer/operator_string.md index 836728c18..f2f99cae7 100644 --- a/doc/mkdocs/docs/api/json_pointer/operator_string.md +++ b/docs/mkdocs/docs/api/json_pointer/operator_string.md @@ -19,6 +19,22 @@ operator string_t() const } ``` +## Examples + +??? example + + The example shows how JSON Pointers can be implicitly converted to strings. + + ```cpp + --8<-- "examples/json_pointer__operator_string.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_pointer__operator_string.output" + ``` + ## Version history - Since version 2.0.0. diff --git a/doc/mkdocs/docs/api/json_pointer/parent_pointer.md b/docs/mkdocs/docs/api/json_pointer/parent_pointer.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/parent_pointer.md rename to docs/mkdocs/docs/api/json_pointer/parent_pointer.md diff --git a/doc/mkdocs/docs/api/json_pointer/pop_back.md b/docs/mkdocs/docs/api/json_pointer/pop_back.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/pop_back.md rename to docs/mkdocs/docs/api/json_pointer/pop_back.md diff --git a/doc/mkdocs/docs/api/json_pointer/push_back.md b/docs/mkdocs/docs/api/json_pointer/push_back.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/push_back.md rename to docs/mkdocs/docs/api/json_pointer/push_back.md diff --git a/doc/mkdocs/docs/api/json_pointer/string_t.md b/docs/mkdocs/docs/api/json_pointer/string_t.md similarity index 51% rename from doc/mkdocs/docs/api/json_pointer/string_t.md rename to docs/mkdocs/docs/api/json_pointer/string_t.md index f18b51b81..c8527bc9c 100644 --- a/doc/mkdocs/docs/api/json_pointer/string_t.md +++ b/docs/mkdocs/docs/api/json_pointer/string_t.md @@ -7,6 +7,22 @@ The string type used for the reference tokens making up the JSON pointer. See [`basic_json::string_t`](../basic_json/string_t.md) for more information. +## Examples + +??? example + + The example shows the type `string_t` and its relation to `basic_json::string_t`. + + ```cpp + --8<-- "examples/json_pointer__string_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_pointer__string_t.output" + ``` + ## Version history - Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/json_pointer/to_string.md b/docs/mkdocs/docs/api/json_pointer/to_string.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/to_string.md rename to docs/mkdocs/docs/api/json_pointer/to_string.md diff --git a/doc/mkdocs/docs/api/json_sax/binary.md b/docs/mkdocs/docs/api/json_sax/binary.md similarity index 56% rename from doc/mkdocs/docs/api/json_sax/binary.md rename to docs/mkdocs/docs/api/json_sax/binary.md index e9a1d3974..753e99c00 100644 --- a/doc/mkdocs/docs/api/json_sax/binary.md +++ b/docs/mkdocs/docs/api/json_sax/binary.md @@ -19,6 +19,22 @@ Whether parsing should proceed. It is safe to move the passed binary value. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse__binary.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse__binary.output" + ``` + ## Version history - Added in version 3.8.0. diff --git a/doc/mkdocs/docs/api/json_sax/boolean.md b/docs/mkdocs/docs/api/json_sax/boolean.md similarity index 53% rename from doc/mkdocs/docs/api/json_sax/boolean.md rename to docs/mkdocs/docs/api/json_sax/boolean.md index a5a8ddcb7..78163b331 100644 --- a/doc/mkdocs/docs/api/json_sax/boolean.md +++ b/docs/mkdocs/docs/api/json_sax/boolean.md @@ -15,6 +15,22 @@ A boolean value was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/json_sax/end_array.md b/docs/mkdocs/docs/api/json_sax/end_array.md new file mode 100644 index 000000000..46b4c7a4b --- /dev/null +++ b/docs/mkdocs/docs/api/json_sax/end_array.md @@ -0,0 +1,31 @@ +# nlohmann::json_sax::end_array + +```cpp +virtual bool end_array() = 0; +``` + +The end of an array was read. + +## Return value + +Whether parsing should proceed. + +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + +## Version history + +- Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/json_sax/end_object.md b/docs/mkdocs/docs/api/json_sax/end_object.md new file mode 100644 index 000000000..8df0ab4e1 --- /dev/null +++ b/docs/mkdocs/docs/api/json_sax/end_object.md @@ -0,0 +1,31 @@ +# nlohmann::json_sax::end_object + +```cpp +virtual bool end_object() = 0; +``` + +The end of an object was read. + +## Return value + +Whether parsing should proceed. + +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + +## Version history + +- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/index.md b/docs/mkdocs/docs/api/json_sax/index.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/index.md rename to docs/mkdocs/docs/api/json_sax/index.md diff --git a/doc/mkdocs/docs/api/json_sax/key.md b/docs/mkdocs/docs/api/json_sax/key.md similarity index 58% rename from doc/mkdocs/docs/api/json_sax/key.md rename to docs/mkdocs/docs/api/json_sax/key.md index 5e7927256..ebd3ae2b2 100644 --- a/doc/mkdocs/docs/api/json_sax/key.md +++ b/docs/mkdocs/docs/api/json_sax/key.md @@ -19,6 +19,22 @@ Whether parsing should proceed. It is safe to move the passed object key value. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/json_sax/null.md b/docs/mkdocs/docs/api/json_sax/null.md new file mode 100644 index 000000000..71b2a458a --- /dev/null +++ b/docs/mkdocs/docs/api/json_sax/null.md @@ -0,0 +1,31 @@ +# nlohmann::json_sax::null + +```cpp +virtual bool null() = 0; +``` + +A null value was read. + +## Return value + +Whether parsing should proceed. + +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + +## Version history + +- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/number_float.md b/docs/mkdocs/docs/api/json_sax/number_float.md similarity index 62% rename from doc/mkdocs/docs/api/json_sax/number_float.md rename to docs/mkdocs/docs/api/json_sax/number_float.md index 94193280b..e1b3fb60f 100644 --- a/doc/mkdocs/docs/api/json_sax/number_float.md +++ b/docs/mkdocs/docs/api/json_sax/number_float.md @@ -18,6 +18,22 @@ A floating-point number was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/number_integer.md b/docs/mkdocs/docs/api/json_sax/number_integer.md similarity index 56% rename from doc/mkdocs/docs/api/json_sax/number_integer.md rename to docs/mkdocs/docs/api/json_sax/number_integer.md index 00ff2eaa6..8628a655c 100644 --- a/doc/mkdocs/docs/api/json_sax/number_integer.md +++ b/docs/mkdocs/docs/api/json_sax/number_integer.md @@ -15,6 +15,22 @@ An integer number was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/number_unsigned.md b/docs/mkdocs/docs/api/json_sax/number_unsigned.md similarity index 58% rename from doc/mkdocs/docs/api/json_sax/number_unsigned.md rename to docs/mkdocs/docs/api/json_sax/number_unsigned.md index 66d0bdac4..7b5974823 100644 --- a/doc/mkdocs/docs/api/json_sax/number_unsigned.md +++ b/docs/mkdocs/docs/api/json_sax/number_unsigned.md @@ -15,6 +15,22 @@ An unsigned integer number was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/parse_error.md b/docs/mkdocs/docs/api/json_sax/parse_error.md similarity index 71% rename from doc/mkdocs/docs/api/json_sax/parse_error.md rename to docs/mkdocs/docs/api/json_sax/parse_error.md index 00f1aa950..d4405d09e 100644 --- a/doc/mkdocs/docs/api/json_sax/parse_error.md +++ b/docs/mkdocs/docs/api/json_sax/parse_error.md @@ -23,6 +23,22 @@ A parse error occurred. Whether parsing should proceed (**must return `#!cpp false`**). +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/start_array.md b/docs/mkdocs/docs/api/json_sax/start_array.md similarity index 63% rename from doc/mkdocs/docs/api/json_sax/start_array.md rename to docs/mkdocs/docs/api/json_sax/start_array.md index d10a6e5a6..8ef10a4ab 100644 --- a/doc/mkdocs/docs/api/json_sax/start_array.md +++ b/docs/mkdocs/docs/api/json_sax/start_array.md @@ -19,6 +19,22 @@ Whether parsing should proceed. Binary formats may report the number of elements. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/start_object.md b/docs/mkdocs/docs/api/json_sax/start_object.md similarity index 63% rename from doc/mkdocs/docs/api/json_sax/start_object.md rename to docs/mkdocs/docs/api/json_sax/start_object.md index fd90f1947..24fedffc3 100644 --- a/doc/mkdocs/docs/api/json_sax/start_object.md +++ b/docs/mkdocs/docs/api/json_sax/start_object.md @@ -19,6 +19,22 @@ Whether parsing should proceed. Binary formats may report the number of elements. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/string.md b/docs/mkdocs/docs/api/json_sax/string.md similarity index 58% rename from doc/mkdocs/docs/api/json_sax/string.md rename to docs/mkdocs/docs/api/json_sax/string.md index 113fe1393..1cb6014ac 100644 --- a/doc/mkdocs/docs/api/json_sax/string.md +++ b/docs/mkdocs/docs/api/json_sax/string.md @@ -19,6 +19,22 @@ Whether parsing should proceed. It is safe to move the passed string value. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md new file mode 100644 index 000000000..d95869b93 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/index.md @@ -0,0 +1,46 @@ +# Macros + +Some aspects of the library can be configured by defining preprocessor macros **before** including the `json.hpp` +header. See also the [macro overview page](../../features/macros.md). + +## Runtime assertions + +- [**JSON_ASSERT(x)**](json_assert.md) - control behavior of runtime assertions + +## Exceptions + +- [**JSON_CATCH_USER(exception)**
**JSON_THROW_USER(exception)**
**JSON_TRY_USER**](json_throw_user.md) - control exceptions +- [**JSON_DIAGNOSTICS**](json_diagnostics.md) - control extended diagnostics +- [**JSON_NOEXCEPTION**](json_noexception.md) - switch off exceptions + +## Language support + +- [**JSON_HAS_CPP_11**
**JSON_HAS_CPP_14**
**JSON_HAS_CPP_17**
**JSON_HAS_CPP_20**](json_has_cpp_11.md) - set supported C++ standard +- [**JSON_HAS_FILESYSTEM**
**JSON_HAS_EXPERIMENTAL_FILESYSTEM**](json_has_filesystem.md) - control `std::filesystem` support +- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support +- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support +- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers +- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers + +## Library version + +- [**JSON_SKIP_LIBRARY_VERSION_CHECK**](json_skip_library_version_check.md) - skip library version check +- [**NLOHMANN_JSON_VERSION_MAJOR**
**NLOHMANN_JSON_VERSION_MINOR**
**NLOHMANN_JSON_VERSION_PATCH**](nlohmann_json_version_major.md) - library version information + +## Type conversions + +- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums +- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions + + +## Comparison behavior + +- [**JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON**](json_use_legacy_discarded_value_comparison.md) - + control comparison of discarded values + +## Serialization/deserialization macros + +- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**
**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**](nlohmann_define_type_intrusive.md) - serialization/deserialization of types _with_ access to private variables +- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**
**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**](nlohmann_define_type_non_intrusive.md) - serialization/deserialization of types _without_ access to private variables +- [**NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)**](nlohmann_json_serialize_enum.md) - serialization/deserialization of enum + types diff --git a/docs/mkdocs/docs/api/macros/json_assert.md b/docs/mkdocs/docs/api/macros/json_assert.md new file mode 100644 index 000000000..a093341a1 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_assert.md @@ -0,0 +1,84 @@ +# JSON_ASSERT + +```cpp +#define JSON_ASSERT(x) /* value */ +``` + +This macro controls which code is executed for [runtime assertions](../../features/assertions.md) of the library. + +## Parameters + +`x` (in) +: expression of scalar type + +## Default definition + +The default value is [`#!cpp assert(x)`](https://en.cppreference.com/w/cpp/error/assert). + +```cpp +#define JSON_ASSERT(x) assert(x) +``` + +Therefore, assertions can be switched off by defining `NDEBUG`. + +## Notes + +- The library uses numerous assertions to guarantee invariants and to abort in case of otherwise undefined behavior + (e.g., when calling [operator[]](../basic_json/operator%5B%5D.md) with a missing object key on a `const` object). See + page [runtime assertions](../../features/assertions.md) for more information. +- Defining the macro to code that does not call `std::abort` may leave the library in an undefined state. +- The macro is undefined outside the library. + +## Examples + +??? example "Example 1: default behavior" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + const json j = {{"key", "value"}}; + auto v = j["missing"]; + } + ``` + + Output: + + ``` + Assertion failed: (m_value.object->find(key) != m_value.object->end()), function operator[], file json.hpp, line 2144. + ``` + +??? example "Example 2: user-defined behavior" + + The assertion reporting can be changed by defining `JSON_ASSERT(x)` differently. + + ```cpp + #include + #include + #define JSON_ASSERT(x) if(!(x)){fprintf(stderr, "assertion error in %s\n", __FUNCTION__); std::abort();} + + #include + + using json = nlohmann::json; + + int main() + { + const json j = {{"key", "value"}}; + auto v = j["missing"]; + } + ``` + + Output: + + ``` + assertion error in operator[] + ``` + +## Version history + +- Added in version 3.9.0. diff --git a/docs/mkdocs/docs/api/macros/json_diagnostics.md b/docs/mkdocs/docs/api/macros/json_diagnostics.md new file mode 100644 index 000000000..d42025092 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_diagnostics.md @@ -0,0 +1,67 @@ +# JSON_DIAGNOSTICS + +```cpp +#define JSON_DIAGNOSTICS /* value */ +``` + +This macro enables [extended diagnostics for exception messages](../../home/exceptions.md#extended-diagnostic-messages). +Possible values are `1` to enable or `0` to disable (default). + +When enabled, exception messages contain a [JSON Pointer](../json_pointer/json_pointer.md) to the JSON value that +triggered the exception. Note that enabling this macro increases the size of every JSON value by one pointer and adds +some runtime overhead. + +The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets +`JSON_DIAGNOSTICS` accordingly. + +## Default definition + +The default value is `0` (extended diagnostics are switched off). + +```cpp +#define JSON_DIAGNOSTICS 0 +``` + +When the macro is not defined, the library will define it to its default value. + +## Notes + +!!! danger "ABI incompatibility" + + 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: `basic_json` objects with differently defined `JSON_DIAGNOSTICS` macros are + not compatible! + +## Examples + +??? example "Example 1: default behavior" + + ```cpp + --8<-- "examples/diagnostics_standard.cpp" + ``` + + Output: + + ``` + --8<-- "examples/diagnostics_standard.output" + ``` + + This exception can be hard to debug if storing the value `#!c "12"` and accessing it is further apart. + +??? example "Example 2: extended diagnostic messages" + + ```cpp + --8<-- "examples/diagnostics_extended.cpp" + ``` + + Output: + + ``` + --8<-- "examples/diagnostics_extended.output" + ``` + + Now the exception message contains a JSON Pointer `/address/housenumber` that indicates which value has the wrong type. + +## Version history + +- Added in version 3.10.0. diff --git a/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md new file mode 100644 index 000000000..ea291f9a0 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md @@ -0,0 +1,135 @@ +# JSON_DISABLE_ENUM_SERIALIZATION + +```cpp +#define JSON_DISABLE_ENUM_SERIALIZATION +``` + +When defined, default serialization and deserialization functions for enums are excluded and have to be provided by the user, for example, using [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) (see [arbitrary type conversions](../../features/arbitrary_types.md) for more details). + +Parsing or serializing an enum will result in a compiler error. + +This works for both unscoped and scoped enums. + +## Default definition + +By default, `#!cpp JSON_DISABLE_ENUM_SERIALIZATION` is not defined. + +```cpp +#undef JSON_DISABLE_ENUM_SERIALIZATION +``` + +## Examples + +??? example "Example 1: Disabled behavior" + + The code below forces the library **not** to create default serialization/deserialization functions `from_json` and `to_json`, meaning the code below **does not** compile. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + int main() + { + // normally invokes to_json serialization function but with JSON_DISABLE_ENUM_SERIALIZATION defined, it does not + const json j = Choice::first; + + // normally invokes from_json parse function but with JSON_DISABLE_ENUM_SERIALIZATION defined, it does not + Choice ch = j.get(); + } + ``` + +??? example "Example 2: Serialize enum macro" + + The code below forces the library **not** to create default serialization/deserialization functions `from_json` and `to_json`, but uses [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) to parse and serialize the enum. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + NLOHMANN_JSON_SERIALIZE_ENUM(Choice, + { + { Choice::first, "first" }, + { Choice::second, "second" }, + }) + + int main() + { + // uses user-defined to_json function defined by macro + const json j = Choice::first; + + // uses user-defined from_json function defined by macro + Choice ch = j.get(); + } + ``` + +??? example "Example 3: User-defined serialization/deserialization functions" + + The code below forces the library **not** to create default serialization/deserialization functions `from_json` and `to_json`, but uses user-defined functions to parse and serialize the enum. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + void from_json(const json& j, Choice& ch) + { + auto value = j.get(); + if (value == "first") + { + ch = Choice::first; + } + else if (value == "second") + { + ch = Choice::second; + } + } + + void to_json(json& j, const Choice& ch) + { + auto value = j.get(); + if (value == "first") + { + ch = Choice::first; + } + else if (value == "second") + { + ch = Choice::second; + } + } + + int main() + { + // uses user-defined to_json function + const json j = Choice::first; + + // uses user-defined from_json function + Choice ch = j.get(); + } + ``` + +## See also + +- [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) \ No newline at end of file diff --git a/docs/mkdocs/docs/api/macros/json_has_cpp_11.md b/docs/mkdocs/docs/api/macros/json_has_cpp_11.md new file mode 100644 index 000000000..f3eaa585c --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_cpp_11.md @@ -0,0 +1,41 @@ +# JSON_HAS_CPP_11, JSON_HAS_CPP_14, JSON_HAS_CPP_17, JSON_HAS_CPP_20 + +```cpp +#define JSON_HAS_CPP_11 +#define JSON_HAS_CPP_14 +#define JSON_HAS_CPP_17 +#define JSON_HAS_CPP_20 +``` + +The library targets C++11, but also supports some features introduced in later C++ versions (e.g., `std::string_view` +support for C++17). For these new features, the library implements some preprocessor checks to determine the C++ +standard. By defining any of these symbols, the internal check is overridden and the provided C++ version is +unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be +detected incorrectly. + +## Default definition + +The default value is detected based on preprocessor macros such as `#!cpp __cplusplus`, `#!cpp _HAS_CXX17`, or +`#!cpp _MSVC_LANG`. + +## Notes + +- `#!cpp JSON_HAS_CPP_11` is always defined. +- All macros are undefined outside the library. + +## Examples + +??? example + + The code below forces the library to use the C++14 standard: + + ```cpp + #define JSON_HAS_CPP_14 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.10.5. diff --git a/docs/mkdocs/docs/api/macros/json_has_filesystem.md b/docs/mkdocs/docs/api/macros/json_has_filesystem.md new file mode 100644 index 000000000..308aea2ac --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_filesystem.md @@ -0,0 +1,43 @@ +# JSON_HAS_FILESYSTEM / JSON_HAS_EXPERIMENTAL_FILESYSTEM + +```cpp +#define JSON_HAS_FILESYSTEM /* value */ +#define JSON_HAS_EXPERIMENTAL_FILESYSTEM /* value */ +``` + +When compiling with C++17, the library provides conversions from and to +[`std::filesystem::path`](https://en.cppreference.com/w/cpp/filesystem/path). As compiler support for filesystem is +limited, the library tries to detect whether +[``/`std::filesystem`](https://en.cppreference.com/w/cpp/header/filesystem) (`JSON_HAS_FILESYSTEM`) or +[``/`std::experimental::filesystem`](https://en.cppreference.com/w/cpp/header/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`. + +## Default definition + +The default value is detected based on the preprocessor macros `#!cpp __cpp_lib_filesystem`, +`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include()`, or +`#!cpp __has_include()`. + +## Notes + +- Note that older compilers or older versions of libstd++ also require the library `stdc++fs` to be linked to for + filesystem support. +- Both macros are undefined outside the library. + +## Examples + +??? example + + The code below forces the library to use the header ``. + + ```cpp + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.10.5. diff --git a/docs/mkdocs/docs/api/macros/json_has_ranges.md b/docs/mkdocs/docs/api/macros/json_has_ranges.md new file mode 100644 index 000000000..ae596979e --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_ranges.md @@ -0,0 +1,18 @@ +# JSON_HAS_RANGES + +```cpp +#define JSON_HAS_RANGES /* value */ +``` + +This macro indicates whether the standard library has any support for ranges. Implies support for concepts. +Possible values are `1` when supported or `0` when unsupported. + +## Default definition + +The default value is detected based on the preprocessor macro `#!cpp __cpp_lib_ranges`. + +When the macro is not defined, the library will define it to its default value. + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_has_three_way_comparison.md b/docs/mkdocs/docs/api/macros/json_has_three_way_comparison.md new file mode 100644 index 000000000..fc1dcb43c --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_three_way_comparison.md @@ -0,0 +1,19 @@ +# JSON_HAS_THREE_WAY_COMPARISON + +```cpp +#define JSON_HAS_THREE_WAY_COMPARISON /* value */ +``` + +This macro indicates whether the compiler and standard library support 3-way comparison. +Possible values are `1` when supported or `0` when unsupported. + +## Default definition + +The default value is detected based on the preprocessor macros `#!cpp __cpp_impl_three_way_comparison` +and `#!cpp __cpp_lib_three_way_comparison`. + +When the macro is not defined, the library will define it to its default value. + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_no_io.md b/docs/mkdocs/docs/api/macros/json_no_io.md new file mode 100644 index 000000000..ef37384a5 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_no_io.md @@ -0,0 +1,35 @@ +# JSON_NO_IO + +```cpp +#define JSON_NO_IO +``` + +When defined, headers ``, ``, ``, ``, and `` are not included and parse functions +relying on these headers are excluded. This is relevant for environments where these I/O functions are disallowed for +security reasons (e.g., Intel Software Guard Extensions (SGX)). + +## Default definition + +By default, `#!cpp JSON_NO_IO` is not defined. + +```cpp +#undef JSON_NO_IO +``` + +## Examples + +??? example + + The code below forces the library not to use the headers ``, ``, ``, ``, and + ``. + + ```cpp + #define JSON_NO_IO 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.10.0. diff --git a/docs/mkdocs/docs/api/macros/json_noexception.md b/docs/mkdocs/docs/api/macros/json_noexception.md new file mode 100644 index 000000000..c801b8567 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_noexception.md @@ -0,0 +1,45 @@ +# JSON_NOEXCEPTION + +```cpp +#define JSON_NOEXCEPTION +``` + +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 +`#!cpp std::abort()`. + +The same effect is achieved by setting the compiler flag `-fno-exceptions`. + +## Default definition + +By default, the macro is not defined. + +```cpp +#undef JSON_NOEXCEPTION +``` + +## Notes + +The explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not +available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). + +## Examples + +??? example + + The code below switches off exceptions in the library. + + ```cpp + #define JSON_NOEXCEPTION 1 + #include + + ... + ``` + +## See also + +- [Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for more information how to switch off exceptions + +## Version history + +Added in version 2.1.0. diff --git a/docs/mkdocs/docs/api/macros/json_skip_library_version_check.md b/docs/mkdocs/docs/api/macros/json_skip_library_version_check.md new file mode 100644 index 000000000..c9a743c18 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_skip_library_version_check.md @@ -0,0 +1,37 @@ +# JSON_SKIP_LIBRARY_VERSION_CHECK + +```cpp +#define JSON_SKIP_LIBRARY_VERSION_CHECK +``` + +When defined, the library will not create a compiler warning when a different version of the library was already +included. + +## Default definition + +By default, the macro is not defined. + +```cpp +#undef JSON_SKIP_LIBRARY_VERSION_CHECK +``` + +## Notes + +!!! danger "ABI compatibility" + + Mixing different library versions in the same code can be a problem as the different versions may not be ABI + compatible. + +## Examples + +!!! example + + The following warning will be shown in case a different version of the library was already included: + + ``` + Already included a different version of the library! + ``` + +## Version history + +Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_skip_unsupported_compiler_check.md b/docs/mkdocs/docs/api/macros/json_skip_unsupported_compiler_check.md new file mode 100644 index 000000000..374fa4c27 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_skip_unsupported_compiler_check.md @@ -0,0 +1,33 @@ +# JSON_SKIP_UNSUPPORTED_COMPILER_CHECK + +```cpp +#define 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 +use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used. + +## Default definition + +By default, the macro is not defined. + +```cpp +#undef JSON_SKIP_UNSUPPORTED_COMPILER_CHECK +``` + +## Examples + +??? example + + The code below switches off the check whether the compiler is supported. + + ```cpp + #define JSON_SKIP_UNSUPPORTED_COMPILER_CHECK 1 + #include + + ... + ``` + +## Version history + +Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/macros/json_throw_user.md b/docs/mkdocs/docs/api/macros/json_throw_user.md new file mode 100644 index 000000000..e10db90e4 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_throw_user.md @@ -0,0 +1,75 @@ +# JSON_CATCH_USER, JSON_THROW_USER, JSON_TRY_USER + +```cpp +// (1) +#define JSON_CATCH_USER(exception) /* value */ +// (2) +#define JSON_THROW_USER(exception) /* value */ +// (3) +#define JSON_TRY_USER /* value */ +``` + +Controls how exceptions are handled by the library. + +1. This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library. + The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range` + 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. +2. 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 + undefined behavior. +3. This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope. + +## Parameters + +`exception` (in) +: an exception type + +## Default definition + +By default, the macros map to their respective C++ keywords: + +```cpp +#define JSON_CATCH_USER(exception) catch(exception) +#define JSON_THROW_USER(exception) throw exception +#define JSON_TRY_USER try +``` + +When exceptions are switched off, the `#!cpp try` block is executed unconditionally, and throwing exceptions is +replaced by calling [`std::abort`](https://en.cppreference.com/w/cpp/utility/program/abort) to make reaching the +`#!cpp throw` branch abort the process. + +```cpp +#define JSON_THROW_USER(exception) std::abort() +#define JSON_TRY_USER if (true) +#define JSON_CATCH_USER(exception) if (false) +``` + +## Examples + +??? example + + The code below switches off exceptions and creates a log entry with a detailed error message in case of errors. + + ```cpp + #include + + #define JSON_TRY_USER if(true) + #define JSON_CATCH_USER(exception) if(false) + #define JSON_THROW_USER(exception) \ + {std::clog << "Error in " << __FILE__ << ":" << __LINE__ \ + << " (function " << __FUNCTION__ << ") - " \ + << (exception).what() << std::endl; \ + std::abort();} + + #include + ``` + +## See also + +- [Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for more information how to switch off exceptions +- [JSON_NOEXCEPTION](JSON_NOEXCEPTION) - switch off exceptions + +## Version history + +- Added in version 3.1.0. diff --git a/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md new file mode 100644 index 000000000..3ee81b061 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md @@ -0,0 +1,56 @@ +# JSON_USE_IMPLICIT_CONVERSIONS + +```cpp +#define JSON_USE_IMPLICIT_CONVERSIONS /* value */ +``` + +When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on. The +value directly affects [`operator ValueType`](../basic_json/operator_ValueType.md). + +Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which +sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly. + +## Default definition + +By default, implicit conversions are enabled. + +```cpp +#define JSON_USE_IMPLICIT_CONVERSIONS 1 +``` + +## Notes + +!!! info "Future behavior change" + + Implicit conversions will be switched off by default in the next major release of the library. + + You can prepare existing code by already defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` and replace any implicit + conversions with calls to [`get`](../basic_json/get.md). + +## Examples + +??? example + + This is an example for an implicit conversion: + + ```cpp + json j = "Hello, world!"; + std::string s = j; + ``` + + When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be + written like this: + + ```cpp + json j = "Hello, world!"; + auto s = j.get(); + ``` + +## See also + +- [**operator ValueType**](../basic_json/operator_ValueType.md) - get a value (implicit) +- [**get**](../basic_json/get.md) - get a value (explicit) + +## Version history + +- Added in version 3.9.0. diff --git a/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md b/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md new file mode 100644 index 000000000..4f630db12 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md @@ -0,0 +1,61 @@ +# JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + +```cpp +#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON /* value */ +``` + +This macro enables the (incorrect) legacy comparison behavior of discarded JSON values. +Possible values are `1` to enable or `0` to disable (default). + +When enabled, comparisons involving at least one discarded JSON value yield results as follows: + +| **Operator** | **Result** | +|--------------|---------------| +| `==` | `#!cpp false` | +| `!=` | `#!cpp true` | +| `<` | `#!cpp false` | +| `<=` | `#!cpp true` | +| `>=` | `#!cpp true` | +| `>` | `#!cpp false` | + +Otherwise, comparisons involving at least one discarded JSON value always yield `#!cpp false`. + +## Default definition + +The default value is `0`. + +```cpp +#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +``` + +When the macro is not defined, the library will define it to its default value. + +## Notes + +!!! warning "Inconsistent behavior in C++20 and beyond" + + When targeting C++20 or above, enabling the legacy comparison behavior is _strongly_ + discouraged. + + - The 3-way comparison operator (`<=>`) will always give the correct result + (`#!cpp std::partial_ordering::unordered`) regardless of the value of + `JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`. + - Overloads for the equality and relational operators emulate the legacy behavior. + + Code outside your control may use either 3-way comparison or the equality and + relational operators, resulting in inconsistent and unpredictable behavior. + + See [`operator<=>`](../basic_json/operator_spaceship.md) for more information on 3-way + comparison. + +!!! warning "Deprecation" + + The legacy comparison behavior is deprecated and may be removed in a future major + version release. + + New code should not depend on it and existing code should try to remove or rewrite + expressions relying on it. + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md new file mode 100644 index 000000000..7269ef081 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md @@ -0,0 +1,124 @@ +# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT + +```cpp +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...) // (1) +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...) // (2) +``` + +These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as +serialization and want to use the member variable names as object keys in that object. The macro is to be defined +**inside** the class/struct to create code for. +Unlike [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](nlohmann_define_type_non_intrusive.md), it can access private members. +The first parameter is the name of the class/struct, and all remaining parameters name the members. + +1. Will use [`at`](../basic_json/at.md) during deserialization and will throw + [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object. +2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the + respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function + default constructs an object and uses its values as the defaults when calling the `value` function. + +## Parameters + +`type` (in) +: name of the type (class, struct) to serialize/deserialize + +`member` (in) +: name of the member variable to serialize/deserialize; up to 64 members can be given as comma-separated list + +## Default definition + +The macros add two friend functions to the class which take care of the serialization and deserialization: + +```cpp +friend void to_json(nlohmann::json&, const type&); +friend void from_json(const nlohmann::json&, type&); +``` + +See examples below for the concrete generated code. + +## Notes + +!!! info "Prerequisites" + + 1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types) + for how to overcome this limitation. + 2. The macro must be used inside the type (class/struct). + +!!! warning "Implementation limits" + + - The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types + with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually. + - The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as + [`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported. + +## Examples + +??? example "Example (1): NLOHMANN_DEFINE_TYPE_INTRUSIVE" + + Consider the following complete example: + + ```cpp hl_lines="21" + --8<-- "examples/nlohmann_define_type_intrusive_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_intrusive_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE` applicable, but not + `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. + - The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is used _inside_ the class. + - A missing key "age" in the deserialization yields an exception. To fall back to the default value, + `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` can be used. + + The macro is equivalent to: + + ```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33" + --8<-- "examples/nlohmann_define_type_intrusive_explicit.cpp" + ``` + +??? example "Example (2): NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT" + + Consider the following complete example: + + ```cpp hl_lines="21" + --8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` applicable, + but not `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`. + - The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` is used _inside_ the class. + - A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used. + + The macro is equivalent to: + + ```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33 34" + --8<-- "examples/nlohmann_define_type_intrusive_with_default_explicit.cpp" + ``` + + Note how a default-initialized `person` object is used in the `from_json` to fill missing values. + +## See also + +- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE / NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_non_intrusive.md) + for a similar macro that can be defined _outside_ the type. +- [Arbitrary Types Conversions](../../features/arbitrary_types.md) for an overview. + +## Version history + +1. Added in version 3.9.0. +2. Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md b/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md new file mode 100644 index 000000000..7ed5a6b43 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md @@ -0,0 +1,124 @@ +# NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT + +```cpp +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...) // (1) +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...) // (2) +``` + +These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as +serialization and want to use the member variable names as object keys in that object. The macro is to be defined +**outside** the class/struct to create code for, but **inside** its namespace. +Unlike [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](nlohmann_define_type_intrusive.md), it **cannot** access private members. +The first parameter is the name of the class/struct, and all remaining parameters name the members. + +1. Will use [`at`](../basic_json/at.md) during deserialization and will throw + [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object. +2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the + respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function + default constructs an object and uses its values as the defaults when calling the `value` function. + +## Parameters + +`type` (in) +: name of the type (class, struct) to serialize/deserialize + +`member` (in) +: name of the (public) member variable to serialize/deserialize; up to 64 members can be given as comma-separated list + +## Default definition + +The macros add two functions to the namespace which take care of the serialization and deserialization: + +```cpp +void to_json(nlohmann::json&, const type&); +void from_json(const nlohmann::json&, type&); +``` + +See examples below for the concrete generated code. + +## Notes + +!!! info "Prerequisites" + + 1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types) + for how to overcome this limitation. + 2. The macro must be used outside the type (class/struct). + 3. The passed members must be public. + +!!! warning "Implementation limits" + + - The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types + with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually. + - The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as + [`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported. + +## Examples + +??? example "Example (1): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE" + + Consider the following complete example: + + ```cpp hl_lines="15" + --8<-- "examples/nlohmann_define_type_non_intrusive_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_non_intrusive_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` applicable. + - The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` is used _outside_ the class, but _inside_ its namespace `ns`. + - A missing key "age" in the deserialization yields an exception. To fall back to the default value, + `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` can be used. + + The macro is equivalent to: + + ```cpp hl_lines="15 16 17 18 19 20 21 22 23 24 25 26 27" + --8<-- "examples/nlohmann_define_type_non_intrusive_explicit.cpp" + ``` + +??? example "Example (2): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT" + + Consider the following complete example: + + ```cpp hl_lines="20" + --8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` + applicable. + - The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` is used _outside_ the class, but _inside_ its namespace `ns`. + - A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used. + + The macro is equivalent to: + + ```cpp hl_lines="20 21 22 23 24 25 26 27 28 29 30 31 32 33" + --8<-- "examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp" + ``` + + Note how a default-initialized `person` object is used in the `from_json` to fill missing values. + +## See also + +- [NLOHMANN_DEFINE_TYPE_INTRUSIVE / NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_intrusive.md) + for a similar macro that can be defined _inside_ the type. +- [Arbitrary Types Conversions](../../features/arbitrary_types.md) for an overview. + +## Version history + +1. Added in version 3.9.0. +2. Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md new file mode 100644 index 000000000..b7204a808 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md @@ -0,0 +1,85 @@ +# NLOHMANN_JSON_SERIALIZE_ENUM + +```cpp +#define NLOHMANN_JSON_SERIALIZE_ENUM(type, conversion...) +``` + +By default, enum values are serialized to JSON as integers. In some cases this could result in undesired behavior. If an +enum is modified or re-ordered after data has been serialized to JSON, the later de-serialized JSON data may be +undefined or a different enum value than was originally intended. + +The `NLOHMANN_JSON_SERIALIZE_ENUM` allows to define a user-defined serialization for every enumerator. + +## Parameters + +`type` (in) +: name of the enum to serialize/deserialize + +`conversion` (in) +: a pair of an enumerator and a JSON serialization; arbitrary pairs can can be given as comma-separated list + +## Default definition + +The macros add two friend functions to the class which take care of the serialization and deserialization: + +```cpp +template +inline void to_json(BasicJsonType& j, const type& e); +template +inline void from_json(const BasicJsonType& j, type& e); +``` + +## Notes + +!!! info "Prerequisites" + + The macro must be used inside the namespace of the enum. + +!!! important "Important notes" + + - When using [`get()`](../basic_json/get.md), undefined JSON values will default to the first specified + conversion. Select this default pair carefully. See example 1 below. + - If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the + list will be returned when converting to or from JSON. See example 2 below. + +## Examples + +??? example "Example 1: Basic usage" + + The example shows how `NLOHMANN_JSON_SERIALIZE_ENUM` can be used to serialize/deserialize both classical enums and + C++11 enum classes: + + ```cpp hl_lines="16 17 18 19 20 21 22 29 30 31 32 33" + --8<-- "examples/nlohmann_json_serialize_enum.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_serialize_enum.output" + ``` + +??? example "Example 2: Multiple conversions for one enumerator" + + The example shows how to use multiple conversions for a single enumerator. In the example, `Color::red` will always + be *serialized* to `"red"`, because the first occurring conversion. The second conversion, however, offers an + alternative *deserialization* from `"rot"` to `Color::red`. + + ```cpp hl_lines="17" + --8<-- "examples/nlohmann_json_serialize_enum_2.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_serialize_enum_2.output" + ``` + +## See also + +- [Specializing enum conversion](../../features/enum_conversion.md) +- [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) + +## Version history + +Added in version 3.4.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_version_major.md b/docs/mkdocs/docs/api/macros/nlohmann_json_version_major.md new file mode 100644 index 000000000..d7a314276 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_version_major.md @@ -0,0 +1,40 @@ +# NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH + +```cpp +#define NLOHMANN_JSON_VERSION_MAJOR /* value */ +#define NLOHMANN_JSON_VERSION_MINOR /* value */ +#define NLOHMANN_JSON_VERSION_PATCH /* value */ +``` + +These macros are defined by the library and contain the version numbers according to +[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). + +## Default definition + +The macros are defined according to the current library version. + +## Examples + +??? example + + The example below shows how `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, and + `NLOHMANN_JSON_VERSION_PATCH` are defined by the library. + + ```cpp + --8<-- "examples/nlohmann_json_version.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_version.output" + ``` + +## See also + +- [meta](../basic_json/meta.md) - returns version information on the library +- [JSON_SKIP_LIBRARY_VERSION_CHECK](json_skip_library_version_check.md) - skip library version check + +## Version history + +- Added in version 3.1.0. diff --git a/docs/mkdocs/docs/api/ordered_json.md b/docs/mkdocs/docs/api/ordered_json.md new file mode 100644 index 000000000..7cfd9f4dd --- /dev/null +++ b/docs/mkdocs/docs/api/ordered_json.md @@ -0,0 +1,32 @@ +# nlohmann::ordered_json + +```cpp +using ordered_json = basic_json; +``` + +This type preserves the insertion order of object keys. + +## Examples + +??? example + + The example below demonstrates how `ordered_json` preserves the insertion order of object keys. + + ```cpp + --8<-- "examples/ordered_json.cpp" + ``` + + Output: + + ```json + --8<-- "examples/ordered_json.output" + ``` + +## See also + +- [ordered_map](ordered_map.md) +- [Object Order](../features/object_order.md) + +## Version history + +Since version 3.9.0. diff --git a/doc/mkdocs/docs/api/ordered_map.md b/docs/mkdocs/docs/api/ordered_map.md similarity index 89% rename from doc/mkdocs/docs/api/ordered_map.md rename to docs/mkdocs/docs/api/ordered_map.md index 74b248ff2..160b85c28 100644 --- a/doc/mkdocs/docs/api/ordered_map.md +++ b/docs/mkdocs/docs/api/ordered_map.md @@ -32,6 +32,12 @@ A minimal map-like container that preserves insertion order for use within [`nlo - **const_iterator** - **size_type** - **value_type** +- **key_compare** - key comparison function +```cpp +std::equal_to // until C++14 + +std::equal_to<> // since C++14 +``` ## Member functions @@ -68,3 +74,4 @@ A minimal map-like container that preserves insertion order for use within [`nlo ## Version history - Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md). +- Added **key_compare** member in version 3.11.0. diff --git a/docs/mkdocs/docs/css/custom.css b/docs/mkdocs/docs/css/custom.css new file mode 100644 index 000000000..7a1008b0b --- /dev/null +++ b/docs/mkdocs/docs/css/custom.css @@ -0,0 +1,4 @@ +/* disable ligatures in code and preformatted blocks */ +code, pre { + font-variant-ligatures: none; +} diff --git a/doc/mkdocs/docs/features/arbitrary_types.md b/docs/mkdocs/docs/features/arbitrary_types.md similarity index 81% rename from doc/mkdocs/docs/features/arbitrary_types.md rename to docs/mkdocs/docs/features/arbitrary_types.md index 67e8a4554..49a541ef5 100644 --- a/doc/mkdocs/docs/features/arbitrary_types.md +++ b/docs/mkdocs/docs/features/arbitrary_types.md @@ -77,7 +77,7 @@ Some important things: * Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). * Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. * When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) -* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. +* In function `from_json`, use function [`at()`](../api/basic_json/at.md) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. @@ -87,16 +87,19 @@ If you just want to serialize/deserialize some structs, the `to_json`/`from_json 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. It will throw an exception in `from_json()` due to a missing value in the JSON object. -- `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. +- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) 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_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) 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, ...)`](../api/macros/nlohmann_define_type_intrusive.md) 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, ...)`](../api/macros/nlohmann_define_type_intrusive.md) 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 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 +!!! info "Implementation limits" - At most 64 member variables can be passed to these macros. + - The current macro implementations are limited to at most 64 member variables. If you want to serialize/deserialize + types with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually. + - The macros only work for the [`nlohmann::json`](../api/json.md) type; other specializations such as + [`nlohmann::ordered_json`](../api/ordered_json.md) are currently unsupported. ??? example diff --git a/docs/mkdocs/docs/features/assertions.md b/docs/mkdocs/docs/features/assertions.md new file mode 100644 index 000000000..a0b118722 --- /dev/null +++ b/docs/mkdocs/docs/features/assertions.md @@ -0,0 +1,104 @@ +# Runtime Assertions + +The code contains numerous debug assertions to ensure class invariants are valid or to detect undefined behavior. +Whereas the former class invariants are nothing to be concerned of, the latter checks for undefined behavior are to +detect bugs in client code. + +## Switch off runtime assertions + +Runtime assertions can be switched off by defining the preprocessor macro `NDEBUG` (see the +[documentation of assert](https://en.cppreference.com/w/cpp/error/assert)) which is the default for release builds. + +## Change assertion behavior + +The behavior of runtime assertions can be changes by defining macro [`JSON_ASSERT(x)`](../api/macros/json_assert.md) +before including the `json.hpp` header. + +## Function with runtime assertions + +### Unchecked object access to a const value + +Function [`operator[]`](../api/basic_json/operator%5B%5D.md) implements unchecked access for objects. Whereas a missing +key is added in case of non-const objects, accessing a const object with a missing key is undefined behavior (think of a +dereferenced null pointer) and yields a runtime assertion. + +If you are not sure whether an element in an object exists, use checked access with the +[`at` function](../api/basic_json/at.md) or call the [`contains` function](../api/basic_json/contains.md) before. + +See also the documentation on [element access](element_access/index.md). + +??? example "Example 1: Missing object key" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + const json j = {{"key", "value"}}; + auto v = j["missing"]; + } + ``` + + Output: + + ``` + Assertion failed: (m_value.object->find(key) != m_value.object->end()), function operator[], file json.hpp, line 2144. + ``` + +### Constructing from an uninitialized iterator range + +Constructing a JSON value from an iterator range (see [constructor](../api/basic_json/basic_json.md)) with an +uninitialized iterator is undefined behavior and yields a runtime assertion. + +??? example "Example 2: Uninitialized iterator range" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + json::iterator it1, it2; + json j(it1, it2); + } + ``` + + Output: + + ``` + Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368. + ``` + +### Operations on uninitialized iterators + +Any operation on uninitialized iterators (i.e., iterators that are not associated with any JSON value) is undefined +behavior and yields a runtime assertion. + +??? example "Example 3: Uninitialized iterator" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + json::iterator it; + ++it; + } + ``` + + Output: + + ``` + Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368. + ``` diff --git a/docs/mkdocs/docs/features/binary_formats/bjdata.md b/docs/mkdocs/docs/features/binary_formats/bjdata.md new file mode 100644 index 000000000..fae55658f --- /dev/null +++ b/docs/mkdocs/docs/features/binary_formats/bjdata.md @@ -0,0 +1,209 @@ +# BJData + +The [BJData format](https://neurojson.org) was derived from and improved upon +[Universal Binary JSON(UBJSON)](https://ubjson.org) specification (Draft 12). +Specifically, it introduces an optimized array container for efficient storage +of N-dimensional packed arrays (**ND-arrays**); it also adds 4 new type markers - +`[u] - uint16`, `[m] - uint32`, `[M] - uint64` and `[h] - float16` - to +unambigiously map common binary numeric types; furthermore, it uses little-endian +(LE) to store all numerics instead of big-endian (BE) as in UBJSON to avoid +unnecessary conversions on commonly available platforms. + +Compared to other binary-JSON-like formats such as MessagePack and CBOR, both BJData and +UBJSON demonstrate a rare combination of being both binary and **quasi-human-readable**. This +is because all semantic elements in BJData and UBJSON, including the data-type markers +and name/string types are directly human-readable. Data stored in the BJData/UBJSON format +are not only compact in size, fast to read/write, but also can be directly searched +or read using simple processing. + +!!! abstract "References" + + - [BJData Specification](https://neurojson.org/bjdata/draft2) + +## Serialization + +The library uses the following mapping from JSON values types to BJData types according to the BJData specification: + +| JSON value type | value/range | BJData type | marker | +|-----------------|-------------------------------------------|----------------|--------| +| null | `null` | null | `Z` | +| boolean | `true` | true | `T` | +| boolean | `false` | false | `F` | +| number_integer | -9223372036854775808..-2147483649 | int64 | `L` | +| number_integer | -2147483648..-32769 | int32 | `l` | +| number_integer | -32768..-129 | int16 | `I` | +| number_integer | -128..127 | int8 | `i` | +| number_integer | 128..255 | uint8 | `U` | +| number_integer | 256..32767 | int16 | `I` | +| number_integer | 32768..65535 | uint16 | `u` | +| number_integer | 65536..2147483647 | int32 | `l` | +| number_integer | 2147483648..4294967295 | uint32 | `m` | +| number_integer | 4294967296..9223372036854775807 | int64 | `L` | +| number_integer | 9223372036854775808..18446744073709551615 | uint64 | `M` | +| number_unsigned | 0..127 | int8 | `i` | +| number_unsigned | 128..255 | uint8 | `U` | +| number_unsigned | 256..32767 | int16 | `I` | +| number_unsigned | 32768..65535 | uint16 | `u` | +| number_unsigned | 65536..2147483647 | int32 | `l` | +| number_unsigned | 2147483648..4294967295 | uint32 | `m` | +| number_unsigned | 4294967296..9223372036854775807 | int64 | `L` | +| number_unsigned | 9223372036854775808..18446744073709551615 | uint64 | `M` | +| number_float | *any value* | float64 | `D` | +| string | *with shortest length indicator* | string | `S` | +| array | *see notes on optimized format/ND-array* | array | `[` | +| object | *see notes on optimized format* | map | `{` | + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any JSON value type can be converted to a BJData value. + + Any BJData output created by `to_bjdata` can be successfully parsed by `from_bjdata`. + +!!! warning "Size constraints" + + The following values can **not** be converted to a BJData value: + + - strings with more than 18446744073709551615 bytes (theoretical) + +!!! info "Unused BJData markers" + + The following markers are not used in the conversion: + + - `Z`: no-op values are not created. + - `C`: single-byte strings are serialized with `S` markers. + +!!! info "NaN/infinity handling" + + If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the `dump()` + function which serializes NaN or Infinity to `null`. + + +!!! info "Endianness" + + A breaking difference between BJData and UBJSON is the endianness + of numerical values. In BJData, all numerical data types (integers + `UiuImlML` and floating-point values `hdD`) are stored in the little-endian (LE) + byte order as opposed to big-endian as used by UBJSON. To adopt LE + to store numeric records avoids unnecessary byte swapping on most modern + computers where LE is used as the default byte order. + +!!! info "Optimized formats" + + The optimized formats for containers are supported: Parameter + `use_size` adds size information to the beginning of a container and + removes the closing marker. Parameter `use_type` further checks + whether all elements of a container have the same type and adds the + type marker to the beginning of the container. The `use_type` + parameter must only be used together with `use_size = true`. + + Note that `use_size = true` alone may result in larger representations - + the benefit of this parameter is that the receiving side is + immediately informed on the number of elements of the container. + +!!! info "ND-array optimized format" + + BJData extends UBJSON's optimized array **size** marker to support + ND-array of uniform numerical data types (referred to as the *packed array*). + For example, 2-D `uint8` integer array `[[1,2],[3,4],[5,6]]` that can be stored + as nested optimized array in UBJSON `[ [$U#i2 1 2 [$U#i2 3 4 [$U#i2 5 6 ]`, + can be further compressed in BJData and stored as `[$U#[$i#i2 2 3 1 2 3 4 5 6` + or `[$U#[i2 i3] 1 2 3 4 5 6`. + + In order to maintain the type and dimension information of an ND-array, + when this library parses a BJData ND-array via `from_bjdata`, it converts the + data into a JSON object, following the **annotated array format** as defined in the + [JData specification (Draft 3)](https://github.com/NeuroJSON/jdata/blob/master/JData_specification.md#annotated-storage-of-n-d-arrays). + For example, the above 2-D `uint8` array can be parsed and accessed as + + ```json + { + "_ArrayType_": "uint8", + "_ArraySize_": [2,3], + "_ArrayData_": [1,2,3,4,5,6] + } + ``` + + In the reversed direction, when `to_bjdata` detects a JSON object in the + above form, it automatically converts such object into a BJData ND-array + to generate compact output. The only exception is that when the 1-D dimensional + vector stored in `"_ArraySize_"` contains a single integer, or two integers with + one being 1, a regular 1-D optimized array is generated. + + The current version of this library has not yet supported automatic + recognition and conversion from a nested JSON array input to a BJData ND-array. + +!!! info "Restrictions in optimized data types for arrays and objects" + + Due to diminished space saving, hampered readability, and increased + security risks, in BJData, the allowed data types following the `$` marker + in an optimized array and object container are restricted to + **non-zero-fixed-length** data types. Therefore, the valid optimized + type markers can only be one of `UiuImlMLhdDC`. This also means other + variable (`[{SH`) or zero-length types (`TFN`) can not be used in an + optimized array or object in BJData. + +!!! info "Binary values" + + If the JSON data contains the binary type, the value stored is a list + of integers, as suggested by the BJData documentation. In particular, + this means that serialization and the deserialization of a JSON + containing binary values into BJData and back will result in a + different JSON object. + + +??? example + + ```cpp + --8<-- "examples/to_bjdata.cpp" + ``` + + Output: + + ```c + --8<-- "examples/to_bjdata.output" + ``` + +## Deserialization + +The library maps BJData types to JSON value types as follows: + +| BJData type | JSON value type | marker | +|-------------|-----------------------------------------|--------| +| no-op | *no value, next value is read* | `N` | +| null | `null` | `Z` | +| false | `false` | `F` | +| true | `true` | `T` | +| float16 | number_float | `h` | +| float32 | number_float | `d` | +| float64 | number_float | `D` | +| uint8 | number_unsigned | `U` | +| int8 | number_integer | `i` | +| uint16 | number_unsigned | `u` | +| int16 | number_integer | `I` | +| uint32 | number_unsigned | `m` | +| int32 | number_integer | `l` | +| uint64 | number_unsigned | `M` | +| int64 | number_integer | `L` | +| string | string | `S` | +| char | string | `C` | +| array | array (optimized values are supported) | `[` | +| ND-array | object (in JData annotated array format)|`[$.#[.`| +| object | object (optimized values are supported) | `{` | + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any BJData value can be converted to a JSON value. + + +??? example + + ```cpp + --8<-- "examples/from_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_bjdata.output" + ``` diff --git a/doc/mkdocs/docs/features/binary_formats/bson.md b/docs/mkdocs/docs/features/binary_formats/bson.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/bson.md rename to docs/mkdocs/docs/features/binary_formats/bson.md diff --git a/doc/mkdocs/docs/features/binary_formats/cbor.md b/docs/mkdocs/docs/features/binary_formats/cbor.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/cbor.md rename to docs/mkdocs/docs/features/binary_formats/cbor.md diff --git a/doc/mkdocs/docs/features/binary_formats/index.md b/docs/mkdocs/docs/features/binary_formats/index.md similarity index 60% rename from doc/mkdocs/docs/features/binary_formats/index.md rename to docs/mkdocs/docs/features/binary_formats/index.md index 3a969a5dc..e74290b09 100644 --- a/doc/mkdocs/docs/features/binary_formats/index.md +++ b/docs/mkdocs/docs/features/binary_formats/index.md @@ -1,7 +1,9 @@ # Binary Formats -Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports +Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over +a network. Hence, the library supports +- [BJData](bjdata.md) (Binary JData), - [BSON](bson.md) (Binary JSON), - [CBOR](cbor.md) (Concise Binary Object Representation), - [MessagePack](messagepack.md), and @@ -15,6 +17,7 @@ to efficiently encode JSON values to byte vectors and to decode such vectors. | Format | Serialization | Deserialization | |-------------|-----------------------------------------------|----------------------------------------------| +| BJData | complete | complete | | BSON | incomplete: top-level value must be an object | incomplete, but all JSON types are supported | | CBOR | complete | incomplete, but all JSON types are supported | | MessagePack | complete | complete | @@ -24,6 +27,7 @@ to efficiently encode JSON values to byte vectors and to decode such vectors. | Format | Binary values | Binary subtypes | |-------------|---------------|-----------------| +| BJData | not supported | not supported | | BSON | supported | supported | | CBOR | supported | supported | | MessagePack | supported | supported | @@ -35,11 +39,14 @@ See [binary values](../binary_values.md) for more information. | Format | canada.json | twitter.json | citm_catalog.json | jeopardy.json | |--------------------|-------------|--------------|-------------------|---------------| -| BSON | 85,8 % | 95,2 % | 95,8 % | 106,7 % | -| CBOR | 50,5 % | 86,3 % | 68,4 % | 88,0 % | -| MessagePack | 50,6 % | 86,0 % | 68,5 % | 87,9 % | -| UBJSON | 53,2 % | 91,3 % | 78,2 % | 96,6 % | -| UBJSON (size) | 58,6 % | 92,3 % | 86,8 % | 97,4 % | -| UBJSON (size+type) | 55,9 % | 92,3 % | 85,0 % | 95,0 % | +| BJData | 53.2 % | 91.1 % | 78.1 % | 96.6 % | +| BJData (size) | 58.6 % | 92.1 % | 86.7 % | 97.4 % | +| BJData (size+tyoe) | 58.6 % | 92.1 % | 86.5 % | 97.4 % | +| BSON | 85.8 % | 95.2 % | 95.8 % | 106.7 % | +| CBOR | 50.5 % | 86.3 % | 68.4 % | 88.0 % | +| MessagePack | 50.5 % | 86.0 % | 68.5 % | 87.9 % | +| UBJSON | 53.2 % | 91.3 % | 78.2 % | 96.6 % | +| UBJSON (size) | 58.6 % | 92.3 % | 86.8 % | 97.4 % | +| UBJSON (size+type) | 55.9 % | 92.3 % | 85.0 % | 95.0 % | Sizes compared to minified JSON value. diff --git a/doc/mkdocs/docs/features/binary_formats/messagepack.md b/docs/mkdocs/docs/features/binary_formats/messagepack.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/messagepack.md rename to docs/mkdocs/docs/features/binary_formats/messagepack.md diff --git a/doc/mkdocs/docs/features/binary_formats/ubjson.md b/docs/mkdocs/docs/features/binary_formats/ubjson.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/ubjson.md rename to docs/mkdocs/docs/features/binary_formats/ubjson.md diff --git a/doc/mkdocs/docs/features/binary_values.md b/docs/mkdocs/docs/features/binary_values.md similarity index 65% rename from doc/mkdocs/docs/features/binary_values.md rename to docs/mkdocs/docs/features/binary_values.md index c58834c05..5ad6433cf 100644 --- a/doc/mkdocs/docs/features/binary_values.md +++ b/docs/mkdocs/docs/features/binary_values.md @@ -1,8 +1,12 @@ # Binary Values -The library implements several [binary formats](binary_formats/index.md) that encode JSON in an efficient way. Most of these formats support binary values; that is, values that have semantics define outside the library and only define a sequence of bytes to be stored. +The library implements several [binary formats](binary_formats/index.md) that encode JSON in an efficient way. Most of +these formats support binary values; that is, values that have semantics define outside the library and only define a +sequence of bytes to be stored. -JSON itself does not have a binary value. As such, binary values are an extension that this library implements to store values received by a binary format. Binary values are never created by the JSON parser, and are only part of a serialized JSON text if they have been created manually or via a binary format. +JSON itself does not have a binary value. As such, binary values are an extension that this library implements to store +values received by a binary format. Binary values are never created by the JSON parser, and are only part of a +serialized JSON text if they have been created manually or via a binary format. ## API for binary values @@ -19,7 +23,9 @@ class json::binary_t { "std::vector" <|-- json::binary_t ``` -By default, binary values are stored as `std::vector`. This type can be changed by providing a template parameter to the `basic_json` type. To store binary subtypes, the storage type is extended and exposed as `json::binary_t`: +By default, binary values are stored as `std::vector`. This type can be changed by providing a template +parameter to the `basic_json` type. To store binary subtypes, the storage type is extended and exposed as +`json::binary_t`: ```cpp auto binary = json::binary_t({0xCA, 0xFE, 0xBA, 0xBE}); @@ -87,7 +93,9 @@ Binary values are serialized differently according to the formats. ### JSON -JSON does not have a binary type, and this library does not introduce a new type as this would break conformance. Instead, binary values are serialized as an object with two keys: `bytes` holds an array of integers, and `subtype` is an integer or `null`. +JSON does not have a binary type, and this library does not introduce a new type as this would break conformance. +Instead, binary values are serialized as an object with two keys: `bytes` holds an array of integers, and `subtype` +is an integer or `null`. ??? example @@ -115,11 +123,72 @@ JSON does not have a binary type, and this library does not introduce a new type !!! warning "No roundtrip for binary values" - The JSON parser will not parse the objects generated by binary values back to binary values. This is by design to remain standards compliant. Serializing binary values to JSON is only implemented for debugging purposes. + The JSON parser will not parse the objects generated by binary values back to binary values. This is by design to + remain standards compliant. Serializing binary values to JSON is only implemented for debugging purposes. + +### BJData + +[BJData](binary_formats/bjdata.md) neither supports binary values nor subtypes, and proposes to serialize binary values +as array of uint8 values. This translation is implemented by the library. + +??? example + + Code: + + ```cpp + // create a binary value of subtype 42 (will be ignored in BJData) + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // convert to BJData + auto v = json::to_bjdata(j); + ``` + + `v` is a `std::vector` with the following 20 elements: + + ```c + 0x7B // '{' + 0x69 0x06 // i 6 (length of the key) + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0x5B // '[' + 0x55 0xCA 0x55 0xFE 0x55 0xBA 0x55 0xBE // content (each byte prefixed with 'U') + 0x5D // ']' + 0x7D // '}' + ``` + + The following code uses the type and size optimization for UBJSON: + + ```cpp + // convert to UBJSON using the size and type optimization + auto v = json::to_bjdata(j, true, true); + ``` + + The resulting vector has 22 elements; the optimization is not effective for examples with few values: + + ```c + 0x7B // '{' + 0x23 0x69 0x01 // '#' 'i' type of the array elements: unsigned integers + 0x69 0x06 // i 6 (length of the key) + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0x5B // '[' array + 0x24 0x55 // '$' 'U' type of the array elements: unsigned integers + 0x23 0x69 0x04 // '#' i 4 number of array elements + 0xCA 0xFE 0xBA 0xBE // content + ``` + + Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would + yield the following value: + + ```json + { + "binary": [202, 254, 186, 190] + } + ``` ### BSON -[BSON](binary_formats/bson.md) supports binary values and subtypes. If a subtype is given, it is used and added as unsigned 8-bit integer. If no subtype is given, the generic binary subtype 0x00 is used. +[BSON](binary_formats/bson.md) supports binary values and subtypes. If a subtype is given, it is used and added as +unsigned 8-bit integer. If no subtype is given, the generic binary subtype 0x00 is used. ??? example @@ -159,7 +228,9 @@ JSON does not have a binary type, and this library does not introduce a new type ### CBOR -[CBOR](binary_formats/cbor.md) supports binary values, but no subtypes. Subtypes will be serialized as tags. Any binary value will be serialized as byte strings. The library will choose the smallest representation using the length of the byte array. +[CBOR](binary_formats/cbor.md) supports binary values, but no subtypes. Subtypes will be serialized as tags. Any binary +value will be serialized as byte strings. The library will choose the smallest representation using the length of the +byte array. ??? example @@ -185,7 +256,8 @@ JSON does not have a binary type, and this library does not introduce a new type 0xCA 0xFE 0xBA 0xBE // content ``` - Note that the subtype is serialized as tag. However, parsing tagged values yield a parse error unless `json::cbor_tag_handler_t::ignore` or `json::cbor_tag_handler_t::store` is passed to `json::from_cbor`. + Note that the subtype is serialized as tag. However, parsing tagged values yield a parse error unless + `json::cbor_tag_handler_t::ignore` or `json::cbor_tag_handler_t::store` is passed to `json::from_cbor`. ```json { @@ -198,7 +270,9 @@ JSON does not have a binary type, and this library does not introduce a new type ### MessagePack -[MessagePack](binary_formats/messagepack.md) supports binary values and subtypes. If a subtype is given, the ext family is used. The library will choose the smallest representation among fixext1, fixext2, fixext4, fixext8, ext8, ext16, and ext32. The subtype is then added as signed 8-bit integer. +[MessagePack](binary_formats/messagepack.md) supports binary values and subtypes. If a subtype is given, the ext family +is used. The library will choose the smallest representation among fixext1, fixext2, fixext4, fixext8, ext8, ext16, and +ext32. The subtype is then added as signed 8-bit integer. If no subtype is given, the bin family (bin8, bin16, bin32) is used. @@ -239,7 +313,8 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used. ### UBJSON -[UBJSON](binary_formats/ubjson.md) neither supports binary values nor subtypes, and proposes to serialize binary values as array of uint8 values. This translation is implemented by the library. +[UBJSON](binary_formats/ubjson.md) neither supports binary values nor subtypes, and proposes to serialize binary values +as array of uint8 values. This translation is implemented by the library. ??? example @@ -251,7 +326,7 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used. j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); // convert to UBJSON - auto v = json::to_msgpack(j); + auto v = json::to_ubjson(j); ``` `v` is a `std::vector` with the following 20 elements: @@ -287,7 +362,8 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used. 0xCA 0xFE 0xBA 0xBE // content ``` - Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would yield the following value: + Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would + yield the following value: ```json { diff --git a/doc/mkdocs/docs/features/comments.md b/docs/mkdocs/docs/features/comments.md similarity index 100% rename from doc/mkdocs/docs/features/comments.md rename to docs/mkdocs/docs/features/comments.md diff --git a/docs/mkdocs/docs/features/element_access/checked_access.md b/docs/mkdocs/docs/features/element_access/checked_access.md new file mode 100644 index 000000000..c4023cce5 --- /dev/null +++ b/docs/mkdocs/docs/features/element_access/checked_access.md @@ -0,0 +1,91 @@ +# Checked access: at + +## Overview + +The [`at`](../../api/basic_json/at.md) member function performs checked access; that is, it returns a reference to the +desired value if it exists and throws a [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) +otherwise. + +??? example "Read access" + + Consider the following JSON value: + + ```json + { + "name": "Mary Smith", + "age": 42, + "hobbies": ["hiking", "reading"] + } + ``` + + Assume the value is parsed to a `json` variable `j`. + + | expression | value | + |-------------------------------|------------------------------------------------------------------------------| + | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | + | `#!cpp j.at("name")` | `#!json "Mary Smith"` | + | `#!cpp j.at("age")` | `#!json 42` | + | `#!cpp j.at("hobbies")` | `#!json ["hiking", "reading"]` | + | `#!cpp j.at("hobbies").at(0)` | `#!json "hiking"` | + | `#!cpp j.at("hobbies").at(1)` | `#!json "reading"` | + +The return value is a reference, so it can be modified by the original value. + +??? example "Write access" + + ```cpp + j.at("name") = "John Smith"; + ``` + + This code produces the following JSON value: + + ```json + { + "name": "John Smith", + "age": 42, + "hobbies": ["hiking", "reading"] + } + ``` + +When accessing an invalid index (i.e., an index greater than or equal to the array size) or the passed object key is +non-existing, an exception is thrown. + +??? example "Accessing via invalid index or missing key" + + ```cpp + j.at("hobbies").at(3) = "cooking"; + ``` + + This code produces the following exception: + + ``` + [json.exception.out_of_range.401] array index 3 is out of range + ``` + + When you [extended diagnostic messages](../../home/exceptions.md#extended-diagnostic-messages) are enabled by + defining [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md), the exception further gives information where + the key or index is missing or out of range. + + ``` + [json.exception.out_of_range.401] (/hobbies) array index 3 is out of range + ``` + +## Notes + + +!!! failure "Exceptions" + + - [`at`](../../api/basic_json/at.md) can only be used with objects (with a string argument) or with arrays (with a + numeric argument). For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error304) + is thrown. + - [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) exceptions are thrown if the + provided key is not found in an object or the provided index is invalid. + +## Summary + +| scenario | non-const value | const value | +|-----------------------------------|------------------------------------------------|------------------------------------------------| +| access to existing object key | reference to existing value is returned | const reference to existing value is returned | +| access to valid array index | reference to existing value is returned | const reference to existing value is returned | +| access to non-existing object key | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | +| access to invalid array index | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | diff --git a/doc/mkdocs/docs/features/element_access/default_value.md b/docs/mkdocs/docs/features/element_access/default_value.md similarity index 100% rename from doc/mkdocs/docs/features/element_access/default_value.md rename to docs/mkdocs/docs/features/element_access/default_value.md diff --git a/doc/mkdocs/docs/features/element_access/index.md b/docs/mkdocs/docs/features/element_access/index.md similarity index 100% rename from doc/mkdocs/docs/features/element_access/index.md rename to docs/mkdocs/docs/features/element_access/index.md diff --git a/doc/mkdocs/docs/features/element_access/unchecked_access.md b/docs/mkdocs/docs/features/element_access/unchecked_access.md similarity index 55% rename from doc/mkdocs/docs/features/element_access/unchecked_access.md rename to docs/mkdocs/docs/features/element_access/unchecked_access.md index bb7228777..1bdea94e7 100644 --- a/doc/mkdocs/docs/features/element_access/unchecked_access.md +++ b/docs/mkdocs/docs/features/element_access/unchecked_access.md @@ -2,9 +2,10 @@ ## Overview -Elements in a JSON object and a JSON array can be accessed via `#!cpp operator[]` similar to a `#!cpp std::map` and a `#!cpp std::vector`, respectively. +Elements in a JSON object and a JSON array can be accessed via [`operator[]`](../../api/basic_json/operator%5B%5D.md) +similar to a `#!cpp std::map` and a `#!cpp std::vector`, respectively. -??? example +??? example "Read access" Consider the following JSON value: @@ -18,18 +19,19 @@ Elements in a JSON object and a JSON array can be accessed via `#!cpp operator[] Assume the value is parsed to a `json` variable `j`. - | expression | value | - | ---------- | ----- | - | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | - | `#!cpp j["name"]` | `#!json "Mary Smith"` | - | `#!cpp j["age"]` | `#!json 42` | - | `#!cpp j["hobbies"]` | `#!json ["hiking", "reading"]` | - | `#!cpp j["hobbies"][0]` | `#!json "hiking"` | - | `#!cpp j["hobbies"][1]` | `#!json "reading"` | + | expression | value | + |-------------------------|------------------------------------------------------------------------------| + | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | + | `#!cpp j["name"]` | `#!json "Mary Smith"` | + | `#!cpp j["age"]` | `#!json 42` | + | `#!cpp j["hobbies"]` | `#!json ["hiking", "reading"]` | + | `#!cpp j["hobbies"][0]` | `#!json "hiking"` | + | `#!cpp j["hobbies"][1]` | `#!json "reading"` | -The return value is a reference, so it can modify the original value. In case the passed object key is non-existing, a `#!json null` value is inserted which can be immediately be overwritten. +The return value is a reference, so it can modify the original value. In case the passed object key is non-existing, a +`#!json null` value is inserted which can be immediately be overwritten. -??? example +??? example "Write access" ```cpp j["name"] = "John Smith"; @@ -47,9 +49,10 @@ The return value is a reference, so it can modify the original value. In case th } ``` -When accessing an invalid index (i.e., an index greater than or equal to the array size), the JSON array is resized such that the passed index is the new maximal index. Intermediate values are filled with `#!json null`. +When accessing an invalid index (i.e., an index greater than or equal to the array size), the JSON array is resized such +that the passed index is the new maximal index. Intermediate values are filled with `#!json null`. -??? example +??? example "Filling up arrays with `#!json null` values" ```cpp j["hobbies"][0] = "running"; @@ -76,17 +79,23 @@ When accessing an invalid index (i.e., an index greater than or equal to the arr - `#!cpp std::vector::operator[]` never inserts a new element. - `#!cpp std::map::operator[]` is not available for const values. - The type `#!cpp json` wraps all JSON value types. It would be impossible to remove `operator[]` for const objects. At the same time, inserting elements for non-const objects is really convenient as it avoids awkward `insert` calls. To this end, we decided to have an inserting non-const behavior for both arrays and objects. + The type `#!cpp json` wraps all JSON value types. It would be impossible to remove + [`operator[]`](../../api/basic_json/operator%5B%5D.md) for const objects. At the same time, inserting elements for + non-const objects is really convenient as it avoids awkward `insert` calls. To this end, we decided to have an + inserting non-const behavior for both arrays and objects. !!! info - The access is unchecked. In case the passed object key does not exist or the passed array index is invalid, no exception is thrown. + The access is unchecked. In case the passed object key does not exist or the passed array index is invalid, no + exception is thrown. !!! danger - It is **undefined behavior** to access a const object with a non-existing key. - It is **undefined behavior** to access a const array with an invalid index. - - In debug mode, an **assertion** will fire in both cases. You can disable assertions by defining the preprocessor symbol `#!cpp NDEBUG` or redefine the macro [`JSON_ASSERT(x)`](../macros.md#json_assertx). + - In debug mode, an **assertion** will fire in both cases. You can disable assertions by defining the preprocessor + symbol `#!cpp NDEBUG` or redefine the macro [`JSON_ASSERT(x)`](../macros.md#json_assertx). See the documentation + on [runtime assertions](../assertions.md) for more information. !!! failure "Exceptions" @@ -94,9 +103,9 @@ When accessing an invalid index (i.e., an index greater than or equal to the arr ## Summary -| scenario | non-const value | const value | -|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------| -| access to existing object key | reference to existing value is returned | const reference to existing value is returned | -| access to valid array index | reference to existing value is returned | const reference to existing value is returned | -| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; assertion in debug mode | -| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; assertion in debug mode | +| scenario | non-const value | const value | +|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| +| access to existing object key | reference to existing value is returned | const reference to existing value is returned | +| access to valid array index | reference to existing value is returned | const reference to existing value is returned | +| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode | +| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode | diff --git a/doc/mkdocs/docs/features/enum_conversion.md b/docs/mkdocs/docs/features/enum_conversion.md similarity index 67% rename from doc/mkdocs/docs/features/enum_conversion.md rename to docs/mkdocs/docs/features/enum_conversion.md index 8f474a702..59ffbd5f1 100644 --- a/doc/mkdocs/docs/features/enum_conversion.md +++ b/docs/mkdocs/docs/features/enum_conversion.md @@ -24,8 +24,8 @@ NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, { }) ``` -The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` -while avoiding repetition and boilerplate serialization code. +The [`NLOHMANN_JSON_SERIALIZE_ENUM()` macro](../api/macros/nlohmann_json_serialize_enum.md) declares a set of +`to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serialization code. ## Usage @@ -45,10 +45,11 @@ assert(jPi.get() == TS_INVALID ); ## Notes -Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above, +Just as in [Arbitrary Type Conversions](arbitrary_types.md) above, -- `NLOHMANN_JSON_SERIALIZE_ENUM()` MUST be declared in your enum type's namespace (which can be the global namespace), - or the library will not be able to locate it, and it will default to integer serialization. +- [`NLOHMANN_JSON_SERIALIZE_ENUM()`](../api/macros/nlohmann_json_serialize_enum.md) MUST be declared in your enum type's + namespace (which can be the global namespace), or the library will not be able to locate it, and it will default to + integer serialization. - It MUST be available (e.g., proper headers must be included) everywhere you use the conversions. Other Important points: @@ -57,3 +58,4 @@ Other Important points: default pair carefully. - If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. +- To disable the default serialization of enumerators as integers and force a compiler error instead, see [`JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). diff --git a/doc/mkdocs/docs/features/iterators.md b/docs/mkdocs/docs/features/iterators.md similarity index 98% rename from doc/mkdocs/docs/features/iterators.md rename to docs/mkdocs/docs/features/iterators.md index 46f28f189..ce627e012 100644 --- a/doc/mkdocs/docs/features/iterators.md +++ b/docs/mkdocs/docs/features/iterators.md @@ -113,7 +113,7 @@ for (auto& [key, val] : j_object.items()) ```cpp json j = {1, 2, 3, 4}; - for (auto it = j.begin(); it != j.end(); ++it) + for (auto it = j.rbegin(); it != j.rend(); ++it) { std::cout << *it << std::endl; } diff --git a/doc/mkdocs/docs/features/json_patch.md b/docs/mkdocs/docs/features/json_patch.md similarity index 100% rename from doc/mkdocs/docs/features/json_patch.md rename to docs/mkdocs/docs/features/json_patch.md diff --git a/doc/mkdocs/docs/features/json_pointer.md b/docs/mkdocs/docs/features/json_pointer.md similarity index 92% rename from doc/mkdocs/docs/features/json_pointer.md rename to docs/mkdocs/docs/features/json_pointer.md index a7861ec7d..a3980b4c6 100644 --- a/doc/mkdocs/docs/features/json_pointer.md +++ b/docs/mkdocs/docs/features/json_pointer.md @@ -18,11 +18,11 @@ Consider the following JSON document } ``` -Then every value inside the JSON document can be idientified as follows: +Then every value inside the JSON document can be identified as follows: | JSON Pointer | JSON value | |-------------------|----------------------------------------------------------------------------------| -| `/` | `#!json {"array":["A","B","C"],"nested":{"one":1,"two":2,"three":[true,false]}}` | +| `` | `#!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` | @@ -34,6 +34,9 @@ Then every value inside the JSON document can be idientified as follows: | `/nested/three/0` | `#!json true` | | `/nested/three/1` | `#!json false` | +Note `/` does not identify the root (i.e., the whole document), but an object entry with empty key `""`. See +[RFC 6901](https://tools.ietf.org/html/rfc6901) for more information. + ## JSON Pointer creation JSON Pointers can be created from a string: diff --git a/docs/mkdocs/docs/features/macros.md b/docs/mkdocs/docs/features/macros.md new file mode 100644 index 000000000..1be95d35d --- /dev/null +++ b/docs/mkdocs/docs/features/macros.md @@ -0,0 +1,153 @@ +# Supported Macros + +Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header. +See also the [API documentation for macros](../api/macros/index.md) for examples and more information. + +## `JSON_ASSERT(x)` + +This macro controls which code is executed for [runtime assertions](assertions.md) of the library. + +See [full documentation of `JSON_ASSERT(x)`](../api/macros/json_assert.md). + +## `JSON_CATCH_USER(exception)` + +This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library. + +See [full documentation of `JSON_CATCH_USER(exception)`](../api/macros/json_throw_user.md). + +## `JSON_DIAGNOSTICS` + +This macro enables extended diagnostics for exception messages. Possible values are `1` to enable or `0` to disable +(default). + +When enabled, exception messages contain a [JSON Pointer](json_pointer.md) to the JSON value that triggered the +exception, see [Extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) for an example. Note +that enabling this macro increases the size of every JSON value by one pointer and adds some runtime overhead. + +The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets +`JSON_DIAGNOSTICS` accordingly. + +See [full documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). + +## `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` +support for C++17). For these new features, the library implements some preprocessor checks to determine the C++ +standard. By defining any of these symbols, the internal check is overridden and the provided C++ version is +unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be +detected incorrectly. + +See [full documentation of `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, and `JSON_HAS_CPP_20`](../api/macros/json_has_cpp_11.md). + +## `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 +for filesystem is limited, the library tries to detect whether ``/`std::filesystem` (`JSON_HAS_FILESYSTEM`) +or ``/`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`. + +See [full documentation of `JSON_HAS_FILESYSTEM` and `JSON_HAS_EXPERIMENTAL_FILESYSTEM`](../api/macros/json_has_filesystem.md). + +## `JSON_NOEXCEPTION` + +Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. + +See [full documentation of `JSON_NOEXCEPTION`](../api/macros/json_noexception.md). + +## `JSON_DISABLE_ENUM_SERIALIZATION` + +When defined, default parse and serialize functions for enums are excluded and have to be provided by the user, for example, using [`NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md). + +See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). + +## `JSON_NO_IO` + +When defined, headers ``, ``, ``, ``, and `` are not included and parse functions +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)). + +See [full documentation of `JSON_NO_IO`](../api/macros/json_no_io.md). + +## `JSON_SKIP_LIBRARY_VERSION_CHECK` + +When defined, the library will not create a compiler warning when a different version of the library was already +included. + +See [full documentation of `JSON_SKIP_LIBRARY_VERSION_CHECK`](../api/macros/json_skip_library_version_check.md). + +## `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 +use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used. + +See [full documentation of `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`](../api/macros/json_skip_unsupported_compiler_check.md). + +## `JSON_THROW_USER(exception)` + +This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. + +See [full documentation of `JSON_THROW_USER(exception)`](../api/macros/json_throw_user.md). + +## `JSON_TRY_USER` + +This macro overrides `#!cpp try` calls inside the library. + +See [full documentation of `JSON_TRY_USER`](../api/macros/json_throw_user.md). + +## `JSON_USE_IMPLICIT_CONVERSIONS` + +When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on. + +See [full documentation of `JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md). + +## `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 +serialization and (2) want to use the member variable names as object keys in that object. + +The macro is to be defined inside the class/struct to create code for. Unlike +[`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members. +The first parameter is the name of the class/struct, and all remaining parameters name the members. + +See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE`](../api/macros/nlohmann_define_type_intrusive.md). + +## `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. The `from_json()` function default constructs +an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function. + +See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_intrusive.md). + +## `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 +serialization and (2) want to use the member variable names as object keys in that object. + +The macro is to be defined inside the namespace of the class/struct to create code for. Private members cannot be +accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios. The +first parameter is the name of the class/struct, and all remaining parameters name the members. + +See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](../api/macros/nlohmann_define_type_non_intrusive.md). + +## `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. The `from_json()` function default constructs +an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function. + +See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_non_intrusive.md). + +## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` + +This macro simplifies the serialization/deserialization of enum types. See +[Specializing enum conversion](enum_conversion.md) for more information. + +See [full documentation of `NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md). + +## `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH` + +These macros are defined by the library and contain the version numbers according to +[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). + +See [full documentation of `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, and `NLOHMANN_JSON_VERSION_PATCH`](../api/macros/nlohmann_json_version_major.md). diff --git a/doc/mkdocs/docs/features/merge_patch.md b/docs/mkdocs/docs/features/merge_patch.md similarity index 100% rename from doc/mkdocs/docs/features/merge_patch.md rename to docs/mkdocs/docs/features/merge_patch.md diff --git a/doc/mkdocs/docs/features/object_order.md b/docs/mkdocs/docs/features/object_order.md similarity index 88% rename from doc/mkdocs/docs/features/object_order.md rename to docs/mkdocs/docs/features/object_order.md index 0768f8020..3ee16a90e 100644 --- a/doc/mkdocs/docs/features/object_order.md +++ b/docs/mkdocs/docs/features/object_order.md @@ -42,30 +42,13 @@ If you do want to preserve the **insertion order**, you can try the type [`nlohm ??? example ```cpp - #include - #include - - using ordered_json = nlohmann::ordered_json; - - int main() - { - ordered_json j; - j["one"] = 1; - j["two"] = 2; - j["three"] = 3; - - std::cout << j.dump(2) << '\n'; - } + --8<-- "examples/ordered_json.cpp" ``` Output: ```json - { - "one": 1, - "two": 2, - "three": 3 - } + --8<-- "examples/ordered_json.output" ``` 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)). diff --git a/doc/mkdocs/docs/features/parsing/index.md b/docs/mkdocs/docs/features/parsing/index.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/index.md rename to docs/mkdocs/docs/features/parsing/index.md diff --git a/doc/mkdocs/docs/features/parsing/json_lines.md b/docs/mkdocs/docs/features/parsing/json_lines.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/json_lines.md rename to docs/mkdocs/docs/features/parsing/json_lines.md diff --git a/doc/mkdocs/docs/features/parsing/parse_exceptions.md b/docs/mkdocs/docs/features/parsing/parse_exceptions.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/parse_exceptions.md rename to docs/mkdocs/docs/features/parsing/parse_exceptions.md diff --git a/doc/mkdocs/docs/features/parsing/parser_callbacks.md b/docs/mkdocs/docs/features/parsing/parser_callbacks.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/parser_callbacks.md rename to docs/mkdocs/docs/features/parsing/parser_callbacks.md diff --git a/doc/mkdocs/docs/features/parsing/sax_interface.md b/docs/mkdocs/docs/features/parsing/sax_interface.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/sax_interface.md rename to docs/mkdocs/docs/features/parsing/sax_interface.md diff --git a/doc/mkdocs/docs/features/types/index.md b/docs/mkdocs/docs/features/types/index.md similarity index 100% rename from doc/mkdocs/docs/features/types/index.md rename to docs/mkdocs/docs/features/types/index.md diff --git a/doc/mkdocs/docs/features/types/number_handling.md b/docs/mkdocs/docs/features/types/number_handling.md similarity index 99% rename from doc/mkdocs/docs/features/types/number_handling.md rename to docs/mkdocs/docs/features/types/number_handling.md index dd6507353..03d8c9c69 100644 --- a/doc/mkdocs/docs/features/types/number_handling.md +++ b/docs/mkdocs/docs/features/types/number_handling.md @@ -275,7 +275,7 @@ The rationale is twofold: ### Determine number types -As the example in [Number conversion](#number_conversion) shows, there are different functions to determine the type of +As the example in [Number conversion](#number-conversion) shows, there are different functions to determine the type of the stored number: - [`is_number()`](../../api/basic_json/is_number.md) returns `#!c true` for any number type diff --git a/doc/mkdocs/docs/home/code_of_conduct.md b/docs/mkdocs/docs/home/code_of_conduct.md similarity index 100% rename from doc/mkdocs/docs/home/code_of_conduct.md rename to docs/mkdocs/docs/home/code_of_conduct.md diff --git a/doc/mkdocs/docs/home/design_goals.md b/docs/mkdocs/docs/home/design_goals.md similarity index 100% rename from doc/mkdocs/docs/home/design_goals.md rename to docs/mkdocs/docs/home/design_goals.md diff --git a/doc/mkdocs/docs/home/exceptions.md b/docs/mkdocs/docs/home/exceptions.md similarity index 92% rename from doc/mkdocs/docs/home/exceptions.md rename to docs/mkdocs/docs/home/exceptions.md index 1241926cf..c9885ae6f 100644 --- a/doc/mkdocs/docs/home/exceptions.md +++ b/docs/mkdocs/docs/home/exceptions.md @@ -28,9 +28,9 @@ class json::parse_error { ### Switch off exceptions -Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`). +Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol [`JSON_NOEXCEPTION`](../api/macros/json_noexception.md). In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`). -Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. +Note that [`JSON_THROW_USER`](../api/macros/json_throw_user.md) should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. ??? example @@ -52,6 +52,8 @@ Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). +See [documentation of `JSON_TRY_USER`, `JSON_CATCH_USER` and `JSON_THROW_USER`](../api/macros/json_throw_user.md) for more information. + ### Extended diagnostic messages Exceptions in the library are thrown in the local context of the JSON value they are detected. This makes detailed diagnostics messages, and hence debugging, difficult. @@ -88,6 +90,7 @@ As this global context comes at the price of storing one additional pointer per Now the exception message contains a JSON Pointer `/address/housenumber` that indicates which value has the wrong type. +See [documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) for more information. ## Parse errors @@ -268,7 +271,7 @@ In a JSON Pointer, only `~0` and `~1` are valid escape sequences. A JSON Pointer array index must be a number. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.parse_error.109] parse error: array index 'one' is not a number @@ -292,19 +295,34 @@ When parsing CBOR or MessagePack, the byte vector ends before the complete value ### json.exception.parse_error.112 -Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +An unexpected byte was read in a [binary format](../features/binary_formats/index.md) or length information is invalid ([BSON](../features/binary_formats/bson.md)). -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0x1C ``` + ``` + [json.exception.parse_error.112] parse error at byte 1: syntax error while parsing MessagePack value: invalid byte: 0xC1 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x02 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x02 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BSON string: string length must be at least 1, is -2147483648 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1 + ``` ### json.exception.parse_error.113 While parsing a map key, a value that is not a string has been read. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF @@ -371,7 +389,7 @@ The iterators passed to constructor `basic_json(InputIT first, InputIT last)` ar In the [erase](../api/basic_json/erase.md) or insert function, the passed iterator `pos` does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.invalid_iterator.202] iterator does not fit current value @@ -535,7 +553,7 @@ To create an object from an initializer list, the initializer list must consist During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.302] type must be object, but is null @@ -548,7 +566,7 @@ During implicit or explicit value conversion, the JSON type must be compatible t To retrieve a reference to a value stored in a `basic_json` object with `get_ref`, the type of the reference must match the value type. For instance, for a JSON array, the `ReferenceType` must be `array_t &`. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object @@ -561,7 +579,7 @@ To retrieve a reference to a value stored in a `basic_json` object with `get_ref The `at()` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.304] cannot use at() with string @@ -574,7 +592,7 @@ The `at()` member functions can only be executed for certain JSON types. The `operator[]` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.305] cannot use operator[] with a string argument with array @@ -617,7 +635,7 @@ The `push_back()` and `operator+=` member functions can only be executed for cer The `insert()` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.309] cannot use insert() with array @@ -640,7 +658,7 @@ The `swap()` member functions can only be executed for certain JSON types. The `emplace()` and `emplace_back()` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.311] cannot use emplace() with number @@ -715,7 +733,7 @@ The `dump()` function only works with UTF-8 encoded strings; that is, if you ass The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) -!!! failure "Example message" +!!! failure "Example messages" Serializing `#!json null` to BSON: ``` diff --git a/doc/mkdocs/docs/home/faq.md b/docs/mkdocs/docs/home/faq.md similarity index 100% rename from doc/mkdocs/docs/home/faq.md rename to docs/mkdocs/docs/home/faq.md diff --git a/doc/mkdocs/docs/home/license.md b/docs/mkdocs/docs/home/license.md similarity index 100% rename from doc/mkdocs/docs/home/license.md rename to docs/mkdocs/docs/home/license.md diff --git a/doc/mkdocs/docs/home/releases.md b/docs/mkdocs/docs/home/releases.md similarity index 100% rename from doc/mkdocs/docs/home/releases.md rename to docs/mkdocs/docs/home/releases.md diff --git a/doc/mkdocs/docs/home/sponsors.md b/docs/mkdocs/docs/home/sponsors.md similarity index 100% rename from doc/mkdocs/docs/home/sponsors.md rename to docs/mkdocs/docs/home/sponsors.md diff --git a/doc/mkdocs/docs/images/callback_events.png b/docs/mkdocs/docs/images/callback_events.png similarity index 100% rename from doc/mkdocs/docs/images/callback_events.png rename to docs/mkdocs/docs/images/callback_events.png diff --git a/doc/mkdocs/docs/images/json_syntax_number.png b/docs/mkdocs/docs/images/json_syntax_number.png similarity index 100% rename from doc/mkdocs/docs/images/json_syntax_number.png rename to docs/mkdocs/docs/images/json_syntax_number.png diff --git a/doc/mkdocs/docs/images/range-begin-end.svg b/docs/mkdocs/docs/images/range-begin-end.svg similarity index 100% rename from doc/mkdocs/docs/images/range-begin-end.svg rename to docs/mkdocs/docs/images/range-begin-end.svg diff --git a/doc/mkdocs/docs/images/range-rbegin-rend.svg b/docs/mkdocs/docs/images/range-rbegin-rend.svg similarity index 100% rename from doc/mkdocs/docs/images/range-rbegin-rend.svg rename to docs/mkdocs/docs/images/range-rbegin-rend.svg diff --git a/doc/mkdocs/docs/index.md b/docs/mkdocs/docs/index.md similarity index 100% rename from doc/mkdocs/docs/index.md rename to docs/mkdocs/docs/index.md diff --git a/doc/mkdocs/docs/integration/cmake.md b/docs/mkdocs/docs/integration/cmake.md similarity index 100% rename from doc/mkdocs/docs/integration/cmake.md rename to docs/mkdocs/docs/integration/cmake.md diff --git a/doc/mkdocs/docs/integration/conan/CMakeLists.txt b/docs/mkdocs/docs/integration/conan/CMakeLists.txt similarity index 100% rename from doc/mkdocs/docs/integration/conan/CMakeLists.txt rename to docs/mkdocs/docs/integration/conan/CMakeLists.txt diff --git a/doc/mkdocs/docs/integration/conan/Conanfile.txt b/docs/mkdocs/docs/integration/conan/Conanfile.txt similarity index 100% rename from doc/mkdocs/docs/integration/conan/Conanfile.txt rename to docs/mkdocs/docs/integration/conan/Conanfile.txt diff --git a/doc/mkdocs/docs/integration/conan/example.cpp b/docs/mkdocs/docs/integration/conan/example.cpp similarity index 100% rename from doc/mkdocs/docs/integration/conan/example.cpp rename to docs/mkdocs/docs/integration/conan/example.cpp diff --git a/doc/mkdocs/docs/integration/example.cpp b/docs/mkdocs/docs/integration/example.cpp similarity index 100% rename from doc/mkdocs/docs/integration/example.cpp rename to docs/mkdocs/docs/integration/example.cpp diff --git a/doc/mkdocs/docs/integration/index.md b/docs/mkdocs/docs/integration/index.md similarity index 100% rename from doc/mkdocs/docs/integration/index.md rename to docs/mkdocs/docs/integration/index.md diff --git a/doc/mkdocs/docs/integration/package_managers.md b/docs/mkdocs/docs/integration/package_managers.md similarity index 100% rename from doc/mkdocs/docs/integration/package_managers.md rename to docs/mkdocs/docs/integration/package_managers.md diff --git a/doc/mkdocs/docs/integration/pkg-config.md b/docs/mkdocs/docs/integration/pkg-config.md similarity index 100% rename from doc/mkdocs/docs/integration/pkg-config.md rename to docs/mkdocs/docs/integration/pkg-config.md diff --git a/doc/mkdocs/docs/integration/vcpkg/CMakeLists.txt b/docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt similarity index 100% rename from doc/mkdocs/docs/integration/vcpkg/CMakeLists.txt rename to docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt diff --git a/doc/mkdocs/docs/integration/vcpkg/example.cpp b/docs/mkdocs/docs/integration/vcpkg/example.cpp similarity index 100% rename from doc/mkdocs/docs/integration/vcpkg/example.cpp rename to docs/mkdocs/docs/integration/vcpkg/example.cpp diff --git a/doc/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml similarity index 81% rename from doc/mkdocs/mkdocs.yml rename to docs/mkdocs/mkdocs.yml index ddd55e5c9..c583ed78f 100644 --- a/doc/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -6,7 +6,7 @@ site_url: https://json.nlohmann.me/ # Repository repo_name: nlohmann/json repo_url: https://github.com/nlohmann/json -edit_uri: edit/develop/doc/mkdocs/docs +edit_uri: edit/develop/docs/mkdocs/docs # Copyright copyright: Copyright © 2013 - 2022 Niels Lohmann @@ -42,6 +42,7 @@ nav: - features/arbitrary_types.md - Binary Formats: - features/binary_formats/index.md + - features/binary_formats/bjdata.md - features/binary_formats/bson.md - features/binary_formats/cbor.md - features/binary_formats/messagepack.md @@ -64,6 +65,7 @@ nav: - features/parsing/parse_exceptions.md - features/parsing/parser_callbacks.md - features/parsing/sax_interface.md + - features/assertions.md - features/enum_conversion.md - features/macros.md - Types: @@ -96,6 +98,7 @@ nav: - 'count': api/basic_json/count.md - 'crbegin': api/basic_json/crbegin.md - 'crend': api/basic_json/crend.md + - 'default_object_comparator_t': api/basic_json/default_object_comparator_t.md - 'diff': api/basic_json/diff.md - 'dump': api/basic_json/dump.md - 'emplace': api/basic_json/emplace.md @@ -107,6 +110,7 @@ nav: - 'exception': api/basic_json/exception.md - 'find': api/basic_json/find.md - 'flatten': api/basic_json/flatten.md + - 'from_bjdata': api/basic_json/from_bjdata.md - 'from_bson': api/basic_json/from_bson.md - 'from_cbor': api/basic_json/from_cbor.md - 'from_msgpack': api/basic_json/from_msgpack.md @@ -150,15 +154,16 @@ nav: - 'operator value_t': api/basic_json/operator_value_t.md - 'operator[]': api/basic_json/operator[].md - 'operator=': api/basic_json/operator=.md + - 'operator+=': api/basic_json/operator+=.md - 'operator==': api/basic_json/operator_eq.md - 'operator!=': api/basic_json/operator_ne.md - 'operator<': api/basic_json/operator_lt.md - - 'operator<<': api/basic_json/operator_ltlt.md - - 'operator<=': api/basic_json/operator_le.md - 'operator>': api/basic_json/operator_gt.md - - 'operator>>': api/basic_json/operator_gtgt.md + - 'operator<=': api/basic_json/operator_le.md - 'operator>=': api/basic_json/operator_ge.md - - 'operator+=': api/basic_json/operator+=.md + - 'operator<=>': api/basic_json/operator_spaceship.md + - 'operator<<': api/basic_json/operator_ltlt.md + - 'operator>>': api/basic_json/operator_gtgt.md - 'operator""_json': api/basic_json/operator_literal_json.md - 'operator""_json_pointer': api/basic_json/operator_literal_json_pointer.md - 'out_of_range': api/basic_json/out_of_range.md @@ -176,6 +181,7 @@ nav: - 'string_t': api/basic_json/string_t.md - 'swap': api/basic_json/swap.md - 'std::swap<basic_json>': api/basic_json/std_swap.md + - 'to_bjdata': api/basic_json/to_bjdata.md - 'to_bson': api/basic_json/to_bson.md - 'to_cbor': api/basic_json/to_cbor.md - 'to_msgpack': api/basic_json/to_msgpack.md @@ -232,7 +238,34 @@ nav: - 'ordered_map': api/ordered_map.md - macros: - 'Overview': api/macros/index.md - - 'JSON_ASSERT(x)': api/macros/json_assert.md + - 'JSON_ASSERT': api/macros/json_assert.md + - 'JSON_CATCH_USER': api/macros/json_throw_user.md + - 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md + - 'JSON_DISABLE_ENUM_SERIALIZATION': api/macros/json_disable_enum_serialization.md + - 'JSON_HAS_CPP_11': api/macros/json_has_cpp_11.md + - 'JSON_HAS_CPP_14': api/macros/json_has_cpp_11.md + - 'JSON_HAS_CPP_17': api/macros/json_has_cpp_11.md + - 'JSON_HAS_CPP_20': api/macros/json_has_cpp_11.md + - 'JSON_HAS_EXPERIMENTAL_FILESYSTEM': api/macros/json_has_filesystem.md + - 'JSON_HAS_FILESYSTEM': api/macros/json_has_filesystem.md + - 'JSON_HAS_RANGES': api/macros/json_has_ranges.md + - 'JSON_HAS_THREE_WAY_COMPARISON': api/macros/json_has_three_way_comparison.md + - 'JSON_NOEXCEPTION': api/macros/json_noexception.md + - 'JSON_NO_IO': api/macros/json_no_io.md + - 'JSON_SKIP_LIBRARY_VERSION_CHECK': api/macros/json_skip_library_version_check.md + - 'JSON_SKIP_UNSUPPORTED_COMPILER_CHECK': api/macros/json_skip_unsupported_compiler_check.md + - 'JSON_THROW_USER': api/macros/json_throw_user.md + - 'JSON_TRY_USER': api/macros/json_throw_user.md + - 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md + - 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON': api/macros/json_use_legacy_discarded_value_comparison.md + - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE': api/macros/nlohmann_define_type_intrusive.md + - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_intrusive.md + - 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE': api/macros/nlohmann_define_type_non_intrusive.md + - 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_non_intrusive.md + - 'NLOHMANN_JSON_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.md + - 'NLOHMANN_JSON_VERSION_MAJOR': api/macros/nlohmann_json_version_major.md + - 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md + - 'NLOHMANN_JSON_VERSION_PATCH': api/macros/nlohmann_json_version_major.md # Extras extra: @@ -289,6 +322,10 @@ plugins: lang: en - minify: minify_html: true + - git-revision-date-localized + +extra_css: + - css/custom.css extra_javascript: - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML diff --git a/docs/mkdocs/requirements.txt b/docs/mkdocs/requirements.txt new file mode 100644 index 000000000..aa9fcaf0e --- /dev/null +++ b/docs/mkdocs/requirements.txt @@ -0,0 +1,48 @@ +Babel==2.10.1 +certifi==2021.10.8 +charset-normalizer==2.0.12 +click==8.1.2 +csscompressor==0.9.5 +future==0.18.2 +ghp-import==2.0.2 +gitdb==4.0.9 +GitPython==3.1.27 +htmlmin==0.1.12 +httplib2==0.20.4 +idna==3.3 +importlib-metadata==4.11.3 +Jinja2==3.1.1 +joblib==1.1.0 +jsmin==3.0.1 +livereload==2.6.3 +lunr==0.6.2 +Markdown==3.3.6 +markdown-include==0.6.0 +MarkupSafe==2.1.1 +mergedeep==1.3.4 +mkdocs==1.3.0 +mkdocs-git-revision-date-localized-plugin==1.0.1 +mkdocs-material==8.2.10 +mkdocs-material-extensions==1.0.3 +mkdocs-minify-plugin==0.5.0 +mkdocs-simple-hooks==0.1.5 +nltk==3.7 +packaging==21.3 +plantuml==0.3.0 +plantuml-markdown==3.5.2 +Pygments==2.11.0 +pymdown-extensions==9.3 +pyparsing==3.0.8 +python-dateutil==2.8.2 +pytz==2022.1 +PyYAML==6.0 +pyyaml_env_tag==0.1 +regex==2022.4.24 +requests==2.27.1 +six==1.16.0 +smmap==5.0.0 +tornado==6.1 +tqdm==4.64.0 +urllib3==1.26.9 +watchdog==2.1.7 +zipp==3.8.0 diff --git a/docs/mkdocs/scripts/check_structure.py b/docs/mkdocs/scripts/check_structure.py new file mode 100755 index 000000000..56de6e89f --- /dev/null +++ b/docs/mkdocs/scripts/check_structure.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +import glob +import os.path +import re + +warnings = 0 + + +def report(rule, location, description): + global warnings + warnings += 1 + print(f'{warnings:3}. {location}: {description} [{rule}]') + + +def check_structure(): + expected_sections = [ + 'Template parameters', + 'Specializations', + 'Iterator invalidation', + 'Requirements', + 'Member types', + 'Member functions', + 'Member variables', + 'Static functions', + 'Non-member functions', + 'Literals', + 'Helper classes', + 'Parameters', + 'Return value', + 'Exception safety', + 'Exceptions', + 'Complexity', + 'Possible implementation', + 'Default definition', + 'Notes', + 'Examples', + 'See also', + 'Version history' + ] + + required_sections = [ + 'Examples', + 'Version history' + ] + + files = sorted(glob.glob('api/**/*.md', recursive=True)) + for file in files: + with open(file) as file_content: + section_idx = -1 # the index of the current h2 section + existing_sections = [] # the list of h2 sections in the file + in_initial_code_example = False # whether we are inside the first code example block + previous_line = None # the previous read line + h1sections = 0 # the number of h1 sections in the file + last_overload = 0 # the last seen overload number in the code example + documented_overloads = {} # the overloads that have been documented in the current block + current_section = None # the name of the current section + + for lineno, original_line in enumerate(file_content.readlines()): + line = original_line.strip() + + if line.startswith('# '): + h1sections += 1 + + # there should only be one top-level title + if h1sections > 1: + report('structure/unexpected_section', f'{file}:{lineno+1}', f'unexpected top-level title "{line}"') + h1sections = 1 + + # Overview pages should have a better title + if line == '# Overview': + report('style/title', f'{file}:{lineno+1}', 'overview pages should have a better title than "Overview"') + + # lines longer than 160 characters are bad (unless they are tables) + if len(line) > 160 and '|' not in line: + report('whitespace/line_length', f'{file}:{lineno+1} ({current_section})', f'line is too long ({len(line)} vs. 160 chars)') + + # check if sections are correct + if line.startswith('## '): + # before starting a new section, check if the previous one documented all overloads + if current_section in documented_overloads and last_overload != 0: + if len(documented_overloads[current_section]) > 0 and len(documented_overloads[current_section]) != last_overload: + expected = list(range(1, last_overload+1)) + undocumented = [x for x in expected if x not in documented_overloads[current_section]] + unexpected = [x for x in documented_overloads[current_section] if x not in expected] + if len(undocumented): + report('style/numbering', f'{file}:{lineno} ({current_section})', f'undocumented overloads: {", ".join([f"({x})" for x in undocumented])}') + if len(unexpected): + report('style/numbering', f'{file}:{lineno} ({current_section})', f'unexpected overloads: {", ".join([f"({x})" for x in unexpected])}') + + current_section = line.strip('## ') + existing_sections.append(current_section) + + if current_section in expected_sections: + idx = expected_sections.index(current_section) + if idx <= section_idx: + report('structure/section_order', f'{file}:{lineno+1}', f'section "{current_section}" is in an unexpected order (should be before "{expected_sections[section_idx]}")') + section_idx = idx + else: + if 'index.md' not in file: # index.md files may have a different structure + report('structure/unknown_section', f'{file}:{lineno+1}', f'section "{current_section}" is not part of the expected sections') + + # collect the numbered items of the current section to later check if they match the number of overloads + if last_overload != 0 and not in_initial_code_example: + if len(original_line) and original_line[0].isdigit(): + number = int(re.findall(r"^(\d+).", original_line)[0]) + if current_section not in documented_overloads: + documented_overloads[current_section] = [] + documented_overloads[current_section].append(number) + + # code example + if line == '```cpp' and section_idx == -1: + in_initial_code_example = True + + if in_initial_code_example and line.startswith('//'): + # check numbering of overloads + if any(map(str.isdigit, line)): + number = int(re.findall(r'\d+', line)[0]) + if number != last_overload + 1: + report('style/numbering', f'{file}:{lineno+1}', f'expected number ({number}) to be ({last_overload +1 })') + last_overload = number + + if any(map(str.isdigit, line)) and '(' not in line: + report('style/numbering', f'{file}:{lineno+1}', 'number should be in parentheses: {line}') + + if line == '```' and in_initial_code_example: + in_initial_code_example = False + + # consecutive blank lines are bad + if line == '' and previous_line == '': + report('whitespace/blank_lines', f'{file}:{lineno}-{lineno+1} ({current_section})', 'consecutive blank lines') + + # check that non-example admonitions have titles + untitled_admonition = re.match(r'^(\?\?\?|!!!) ([^ ]+)$', line) + if untitled_admonition and untitled_admonition.group(2) != 'example': + report('style/admonition_title', f'{file}:{lineno} ({current_section})', f'"{untitled_admonition.group(2)}" admonitions should have a title') + + previous_line = line + + if 'index.md' not in file: # index.md files may have a different structure + for required_section in required_sections: + if required_section not in existing_sections: + report('structure/missing_section', f'{file}:{lineno+1}', f'required section "{required_section}" was not found') + + +def check_examples(): + example_files = sorted(glob.glob('../../examples/*.cpp')) + markdown_files = sorted(glob.glob('**/*.md', recursive=True)) + + # check if every example file is used in at least one markdown file + for example_file in example_files: + example_file = os.path.join('examples', os.path.basename(example_file)) + + found = False + for markdown_file in markdown_files: + content = ' '.join(open(markdown_file).readlines()) + if example_file in content: + found = True + break + + if not found: + report('examples/missing', f'{example_file}', 'example file is not used in any documentation file') + + +if __name__ == '__main__': + print(120 * '-') + check_structure() + check_examples() + print(120 * '-') diff --git a/doc/usages/ios.png b/docs/usages/ios.png similarity index 100% rename from doc/usages/ios.png rename to docs/usages/ios.png diff --git a/doc/usages/macos.png b/docs/usages/macos.png similarity index 100% rename from doc/usages/macos.png rename to docs/usages/macos.png diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 079baa723..ed4e6de5f 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -39,7 +39,7 @@ namespace nlohmann namespace detail { template -void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) { if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { @@ -86,7 +86,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) } template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { @@ -96,7 +96,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) } template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { @@ -111,7 +111,7 @@ template < std::is_assignable::value && !std::is_same::value && !is_json_ref::value, int > = 0 > -void from_json(const BasicJsonType& j, StringType& s) +inline void from_json(const BasicJsonType& j, StringType& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { @@ -122,36 +122,38 @@ void from_json(const BasicJsonType& j, StringType& s) } template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { get_arithmetic_value(j, val); } template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) { get_arithmetic_value(j, val); } template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) { get_arithmetic_value(j, val); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) +inline void from_json(const BasicJsonType& j, EnumType& e) { typename std::underlying_type::type val; get_arithmetic_value(j, val); e = static_cast(val); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION // forward_list doesn't have an insert method template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) +inline void from_json(const BasicJsonType& j, std::forward_list& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { @@ -168,7 +170,7 @@ void from_json(const BasicJsonType& j, std::forward_list& l) // valarray doesn't have an insert method template::value, int> = 0> -void from_json(const BasicJsonType& j, std::valarray& l) +inline void from_json(const BasicJsonType& j, std::valarray& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { @@ -193,7 +195,7 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines } template -void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { arr = *j.template get_ptr(); } @@ -237,8 +239,8 @@ template::value, int> = 0> -void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, - priority_tag<0> /*unused*/) +inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) { using std::end; @@ -295,7 +297,7 @@ auto from_json(BasicJsonType&& j, identity_tag> tag) } template -void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) { if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { @@ -307,7 +309,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) template::value, int> = 0> -void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) { if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { @@ -339,7 +341,7 @@ template < typename BasicJsonType, typename ArithmeticType, !std::is_same::value&& !std::is_same::value, int > = 0 > -void from_json(const BasicJsonType& j, ArithmeticType& val) +inline void from_json(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast(j)) { @@ -389,7 +391,7 @@ std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag -void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) +inline void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) { p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); } @@ -401,7 +403,7 @@ std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag -void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) +inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) { t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); } @@ -421,7 +423,7 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t) template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::map& m) +inline void from_json(const BasicJsonType& j, std::map& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { @@ -441,7 +443,7 @@ void from_json(const BasicJsonType& j, std::map& template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::unordered_map& m) +inline void from_json(const BasicJsonType& j, std::unordered_map& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { @@ -460,7 +462,7 @@ void from_json(const BasicJsonType& j, std::unordered_map -void from_json(const BasicJsonType& j, std_fs::path& p) +inline void from_json(const BasicJsonType& j, std_fs::path& p) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { @@ -482,11 +484,16 @@ struct from_json_fn }; } // namespace detail +#ifndef JSON_HAS_CPP_17 /// namespace to hold default `from_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { -constexpr const auto& from_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +#endif +JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) + detail::static_const::value; +#ifndef JSON_HAS_CPP_17 } // namespace +#endif } // namespace nlohmann diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 7628ae011..1d7a86a53 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -267,55 +267,64 @@ struct external_constructor template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept +inline void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); } +template::reference&, typename BasicJsonType::boolean_t>::value, int> = 0> +inline void to_json(BasicJsonType& j, const std::vector::reference& b) noexcept +{ + external_constructor::construct(j, static_cast(b)); +} + template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) +inline void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor::construct(j, s); } template -void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) { external_constructor::construct(j, std::move(s)); } template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept +inline void to_json(BasicJsonType& j, FloatType val) noexcept { external_constructor::construct(j, static_cast(val)); } template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor::construct(j, static_cast(val)); } template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor::construct(j, static_cast(val)); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept +inline void to_json(BasicJsonType& j, EnumType e) noexcept { using underlying_type = typename std::underlying_type::type; external_constructor::construct(j, static_cast(e)); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION template -void to_json(BasicJsonType& j, const std::vector& e) +inline void to_json(BasicJsonType& j, const std::vector& e) { external_constructor::construct(j, e); } @@ -328,39 +337,39 @@ template < typename BasicJsonType, typename CompatibleArrayType, !std::is_same::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor::construct(j, arr); } template -void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) +inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) { external_constructor::construct(j, bin); } template::value, int> = 0> -void to_json(BasicJsonType& j, const std::valarray& arr) +inline void to_json(BasicJsonType& j, const std::valarray& arr) { external_constructor::construct(j, std::move(arr)); } template -void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { external_constructor::construct(j, std::move(arr)); } template < typename BasicJsonType, typename CompatibleObjectType, enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor::construct(j, obj); } template -void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { external_constructor::construct(j, std::move(obj)); } @@ -370,13 +379,13 @@ template < enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) int > = 0 > -void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { external_constructor::construct(j, arr); } template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > -void to_json(BasicJsonType& j, const std::pair& p) +inline void to_json(BasicJsonType& j, const std::pair& p) { j = { p.first, p.second }; } @@ -384,26 +393,26 @@ void to_json(BasicJsonType& j, const std::pair& p) // for https://github.com/nlohmann/json/pull/1134 template>::value, int> = 0> -void to_json(BasicJsonType& j, const T& b) +inline void to_json(BasicJsonType& j, const T& b) { j = { {b.key(), b.value()} }; } template -void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) { j = { std::get(t)... }; } template::value, int > = 0> -void to_json(BasicJsonType& j, const T& t) +inline void to_json(BasicJsonType& j, const T& t) { to_json_tuple_impl(j, t, make_index_sequence::value> {}); } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM template -void to_json(BasicJsonType& j, const std_fs::path& p) +inline void to_json(BasicJsonType& j, const std_fs::path& p) { j = p.string(); } @@ -420,11 +429,16 @@ struct to_json_fn }; } // namespace detail +#ifndef JSON_HAS_CPP_17 /// namespace to hold default `to_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { -constexpr const auto& to_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +#endif +JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) + detail::static_const::value; +#ifndef JSON_HAS_CPP_17 } // namespace +#endif } // namespace nlohmann diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 4041cedba..103f7a752 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -12,6 +12,7 @@ #include // char_traits, string #include // make_pair, move #include // vector +#include // map #include #include @@ -74,7 +75,7 @@ class binary_reader @param[in] adapter input adapter to read from */ - explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter)) + explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) { (void)detail::is_sax_static_asserts {}; } @@ -118,6 +119,7 @@ class binary_reader break; case input_format_t::ubjson: + case input_format_t::bjdata: result = parse_ubjson_internal(); break; @@ -129,7 +131,7 @@ class binary_reader // strict mode: next byte must be EOF if (result && strict) { - if (format == input_format_t::ubjson) + if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) { get_ignore_noop(); } @@ -141,7 +143,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) { return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, - exception_message(format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); + exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); } } @@ -616,7 +618,8 @@ class binary_reader case 0x95: case 0x96: case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); + return get_cbor_array( + conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0x98: // array (one-byte uint8_t for n follows) { @@ -633,13 +636,13 @@ class binary_reader case 0x9A: // array (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); } case 0x9B: // array (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); } case 0x9F: // array (indefinite length) @@ -670,7 +673,7 @@ class binary_reader case 0xB5: case 0xB6: case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); + return get_cbor_object(conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0xB8: // map (one-byte uint8_t for n follows) { @@ -687,13 +690,13 @@ class binary_reader case 0xBA: // map (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); } case 0xBB: // map (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); } case 0xBF: // map (indefinite length) @@ -1340,7 +1343,7 @@ class binary_reader case 0x8D: case 0x8E: case 0x8F: - return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + return get_msgpack_object(conditional_static_cast(static_cast(current) & 0x0Fu)); // fixarray case 0x90: @@ -1359,7 +1362,7 @@ class binary_reader case 0x9D: case 0x9E: case 0x9F: - return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + return get_msgpack_array(conditional_static_cast(static_cast(current) & 0x0Fu)); // fixstr case 0xA0: @@ -1496,7 +1499,7 @@ class binary_reader case 0xDD: // array 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast(len)); } case 0xDE: // map 16 @@ -1508,7 +1511,7 @@ class binary_reader case 0xDF: // map 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast(len)); } // negative fixint @@ -1844,7 +1847,7 @@ class binary_reader get(); // TODO(niels): may we ignore N here? } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) { return false; } @@ -1854,52 +1857,162 @@ class binary_reader case 'U': { std::uint8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'i': { std::int8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'I': { std::int16_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'l': { std::int32_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'L': { std::int64_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); } default: - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::ubjson, concat("expected length type specification (U, i, I, l, L); last byte: 0x", last_token), "string"), nullptr)); + break; } + auto last_token = get_token_string(); + std::string message; + + if (input_format != input_format_t::bjdata) + { + message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; + } + else + { + message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; + } + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); + } + + /*! + @param[out] dim an integer vector storing the ND array dimensions + @return whether reading ND array size vector is successful + */ + bool get_ubjson_ndarray_size(std::vector& dim) + { + std::pair size_and_type; + size_t dimlen = 0; + bool no_ndarray = true; + + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) + { + return false; + } + dim.push_back(dimlen); + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) + { + return false; + } + dim.push_back(dimlen); + } + } + } + else + { + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) + { + return false; + } + dim.push_back(dimlen); + get_ignore_noop(); + } + } + return true; } /*! @param[out] result determined size + @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector + or ndarray dimension is not allowed; `false` means ndarray + is allowed; for output, `true` means an ndarray is found; + is_ndarray can only return `true` when its initial value + is `false` + @param[in] prefix type marker if already read, otherwise set to 0 + @return whether size determination completed */ - bool get_ubjson_size_value(std::size_t& result) + bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) { - switch (get_ignore_noop()) + if (prefix == 0) + { + prefix = get_ignore_noop(); + } + + switch (prefix) { case 'U': { std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } @@ -1910,10 +2023,15 @@ class binary_reader case 'i': { std::int8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char return true; } @@ -1921,10 +2039,15 @@ class binary_reader case 'I': { std::int16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } result = static_cast(number); return true; } @@ -1932,10 +2055,15 @@ class binary_reader case 'l': { std::int32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } result = static_cast(number); return true; } @@ -1943,7 +2071,32 @@ class binary_reader case 'L': { std::int64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } + if (!value_in_range_of(number)) + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), nullptr)); + } + result = static_cast(number); + return true; + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } @@ -1951,13 +2104,112 @@ class binary_reader return true; } - default: + case 'm': { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::ubjson, concat("expected length type specification (U, i, I, l, L) after '#'; last byte: 0x", last_token), "size"), nullptr)); + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + result = conditional_static_cast(number); + return true; } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (!value_in_range_of(number)) + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), nullptr)); + } + result = detail::conditional_static_cast(number); + return true; + } + + case '[': + { + if (input_format != input_format_t::bjdata) + { + break; + } + if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr)); + } + std::vector dim; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) + { + return false; + } + if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector + { + result = dim.at(dim.size() - 1); + return true; + } + if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format + { + for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container + { + if ( i == 0 ) + { + result = 0; + return true; + } + } + + string_t key = "_ArraySize_"; + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) + { + return false; + } + result = 1; + for (auto i : dim) + { + result *= i; + if (result == 0 || result == string_t::npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be string_t::npos as it is used to initialize size in get_ubjson_size_type() + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); + } + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast(i)))) + { + return false; + } + } + is_ndarray = true; + return sax->end_array(); + } + result = 0; + return true; + } + + default: + break; } + auto last_token = get_token_string(); + std::string message; + + if (input_format != input_format_t::bjdata) + { + message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; + } + else + { + message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; + } + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); } /*! @@ -1967,20 +2219,31 @@ class binary_reader for a more compact representation. @param[out] result pair of the size and the type + @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector @return whether pair creation completed */ - bool get_ubjson_size_type(std::pair& result) + bool get_ubjson_size_type(std::pair& result, bool inside_ndarray = false) { result.first = string_t::npos; // size result.second = 0; // type + bool is_ndarray = false; get_ignore_noop(); if (current == '$') { + std::vector bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type + result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) + if (JSON_HEDLEY_UNLIKELY( input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() )) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); + } + + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) { return false; } @@ -1988,21 +2251,37 @@ class binary_reader get_ignore_noop(); if (JSON_HEDLEY_UNLIKELY(current != '#')) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) { return false; } auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::ubjson, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); + exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); } - return get_ubjson_size_value(result.first); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); + if (input_format == input_format_t::bjdata && is_ndarray) + { + if (inside_ndarray) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, + exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); + } + result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters + } + return is_error; } if (current == '#') { - return get_ubjson_size_value(result.first); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); + if (input_format == input_format_t::bjdata && is_ndarray) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, + exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); + } + return is_error; } return true; @@ -2017,7 +2296,7 @@ class binary_reader switch (prefix) { case std::char_traits::eof(): // EOF - return unexpect_eof(input_format_t::ubjson, "value"); + return unexpect_eof(input_format, "value"); case 'T': // true return sax->boolean(true); @@ -2030,43 +2309,125 @@ class binary_reader case 'U': { std::uint8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); + return get_number(input_format, number) && sax->number_unsigned(number); } case 'i': { std::int8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); } case 'I': { std::int16_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); } case 'l': { std::int32_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); } case 'L': { std::int64_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'h': + { + if (input_format != input_format_t::bjdata) + { + break; + } + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte2 << 8u) + byte1); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp&& exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); } case 'd': { float number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + return get_number(input_format, number) && sax->number_float(static_cast(number), ""); } case 'D': { double number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + return get_number(input_format, number) && sax->number_float(static_cast(number), ""); } case 'H': @@ -2077,7 +2438,7 @@ class binary_reader case 'C': // char { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) { return false; } @@ -2085,7 +2446,7 @@ class binary_reader { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, - exception_message(input_format_t::ubjson, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); + exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); } string_t s(1, static_cast(current)); return sax->string(s); @@ -2104,12 +2465,10 @@ class binary_reader return get_ubjson_object(); default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, - exception_message(input_format_t::ubjson, concat("invalid byte: 0x", last_token), "value"), nullptr)); - } + break; } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); } /*! @@ -2123,6 +2482,52 @@ class binary_reader return false; } + // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): + // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} + + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) + { + std::map bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"}, + {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"} + }; + + size_and_type.second &= ~(static_cast(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker + + string_t key = "_ArrayType_"; + if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) + { + return false; + } + + if (size_and_type.second == 'C') + { + size_and_type.second = 'U'; + } + + key = "_ArrayData_"; + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) + { + return false; + } + + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + } + + return (sax->end_array() && sax->end_object()); + } + if (size_and_type.first != string_t::npos) { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) @@ -2185,6 +2590,14 @@ class binary_reader return false; } + // do not accept ND-array size in objects in BJData + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); + } + string_t key; if (size_and_type.first != string_t::npos) { @@ -2256,7 +2669,8 @@ class binary_reader { // get size of following number string std::size_t size{}; - auto res = get_ubjson_size_value(size); + bool no_ndarray = true; + auto res = get_ubjson_size_value(size, no_ndarray); if (JSON_HEDLEY_UNLIKELY(!res)) { return res; @@ -2267,7 +2681,7 @@ class binary_reader for (std::size_t i = 0; i < size; ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) { return false; } @@ -2286,7 +2700,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format_t::ubjson, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); + exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); } switch (result_number) @@ -2313,7 +2727,7 @@ class binary_reader case token_type::literal_or_value: default: return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, - exception_message(input_format_t::ubjson, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); + exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); } } @@ -2362,6 +2776,8 @@ class binary_reader @note This function needs to respect the system's endianness, because bytes in CBOR, MessagePack, and UBJSON are stored in network order (big endian) and therefore need reordering on little endian systems. + On the other hand, BSON and BJData use little endian and should reorder + on big endian systems. */ template bool get_number(const input_format_t format, NumberType& result) @@ -2377,7 +2793,7 @@ class binary_reader } // reverse byte order prior to conversion if necessary - if (is_little_endian != InputIsLittleEndian) + if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) { vec[sizeof(NumberType) - i - 1] = static_cast(current); } @@ -2514,6 +2930,10 @@ class binary_reader error_msg += "BSON"; break; + case input_format_t::bjdata: + error_msg += "BJData"; + break; + case input_format_t::json: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE @@ -2535,6 +2955,9 @@ class binary_reader /// whether we can assume little endianness const bool is_little_endian = little_endianness(); + /// input format + const input_format_t input_format = input_format_t::json; + /// the SAX parser json_sax_t* sax = nullptr; }; diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index e693f235b..5464fa919 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -23,7 +23,7 @@ namespace nlohmann namespace detail { /// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson }; +enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; //////////////////// // input adapters // diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index 406008167..9355137cf 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -233,6 +233,9 @@ class json_sax_dom_parser bool key(string_t& val) { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + // add null at given key and store the reference for later object_element = &(ref_stack.back()->m_value.object->operator[](val)); return true; @@ -240,6 +243,9 @@ class json_sax_dom_parser bool end_object() { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + ref_stack.back()->set_parents(); ref_stack.pop_back(); return true; @@ -259,6 +265,9 @@ class json_sax_dom_parser bool end_array() { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_array()); + ref_stack.back()->set_parents(); ref_stack.pop_back(); return true; diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index cdcdaff1f..028de4047 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -51,9 +51,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci // make sure BasicJsonType is basic_json or const basic_json static_assert(is_basic_json::type>::value, "iter_impl only accepts (const) basic_json"); + // superficial check for the LegacyBidirectionalIterator named requirement + static_assert(std::is_base_of::value + && std::is_base_of::iterator_category>::value, + "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); public: - /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. /// The C++ Standard has never required user-defined iterators to derive from std::iterator. /// A user-defined iterator should provide publicly accessible typedefs named diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index 9994b364c..a75614de1 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -6,6 +6,10 @@ #include // tuple_size, get, tuple_element #include // move +#if JSON_HAS_RANGES + #include // enable_borrowed_range +#endif + #include #include @@ -25,14 +29,14 @@ template class iteration_proxy_value public: using difference_type = std::ptrdiff_t; using value_type = iteration_proxy_value; - using pointer = value_type * ; - using reference = value_type & ; + using pointer = value_type *; + using reference = value_type &; using iterator_category = std::input_iterator_tag; using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; private: /// the iterator - IteratorType anchor; + IteratorType anchor{}; /// an index for arrays (used to create key names) std::size_t array_index = 0; /// last stringified array index @@ -40,15 +44,30 @@ template class iteration_proxy_value /// a string representation of the array index mutable string_type array_index_str = "0"; /// an empty string (to return a reference for primitive values) - const string_type empty_str{}; + string_type empty_str{}; public: - explicit iteration_proxy_value(IteratorType it) noexcept + explicit iteration_proxy_value() = default; + explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) + noexcept(std::is_nothrow_move_constructible::value + && std::is_nothrow_default_constructible::value) : anchor(std::move(it)) + , array_index(array_index_) {} + iteration_proxy_value(iteration_proxy_value const&) = default; + iteration_proxy_value& operator=(iteration_proxy_value const&) = default; + // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions + iteration_proxy_value(iteration_proxy_value&&) + noexcept(std::is_nothrow_move_constructible::value + && std::is_nothrow_move_constructible::value) = default; + iteration_proxy_value& operator=(iteration_proxy_value&&) + noexcept(std::is_nothrow_move_assignable::value + && std::is_nothrow_move_assignable::value) = default; + ~iteration_proxy_value() = default; + /// dereference operator (needed for range-based for) - iteration_proxy_value& operator*() + const iteration_proxy_value& operator*() const { return *this; } @@ -62,6 +81,14 @@ template class iteration_proxy_value return *this; } + iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) + { + auto tmp = iteration_proxy_value(anchor, array_index); + ++anchor; + ++array_index; + return tmp; + } + /// equality operator (needed for InputIterator) bool operator==(const iteration_proxy_value& o) const { @@ -122,25 +149,34 @@ template class iteration_proxy { private: /// the container to iterate - typename IteratorType::reference container; + typename IteratorType::pointer container = nullptr; public: + explicit iteration_proxy() = default; + /// construct iteration proxy from a container explicit iteration_proxy(typename IteratorType::reference cont) noexcept - : container(cont) {} + : container(&cont) {} + + iteration_proxy(iteration_proxy const&) = default; + iteration_proxy& operator=(iteration_proxy const&) = default; + iteration_proxy(iteration_proxy&&) noexcept = default; + iteration_proxy& operator=(iteration_proxy&&) noexcept = default; + ~iteration_proxy() = default; /// return iterator begin (needed for range-based for) - iteration_proxy_value begin() noexcept + iteration_proxy_value begin() const noexcept { - return iteration_proxy_value(container.begin()); + return iteration_proxy_value(container->begin()); } /// return iterator end (needed for range-based for) - iteration_proxy_value end() noexcept + iteration_proxy_value end() const noexcept { - return iteration_proxy_value(container.end()); + return iteration_proxy_value(container->end()); } }; + // Structured Bindings Support // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 @@ -187,3 +223,8 @@ class tuple_element> #pragma clang diagnostic pop #endif } // namespace std + +#if JSON_HAS_RANGES + template + inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy> = true; +#endif diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index f636b908a..706f1b971 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -37,6 +37,12 @@ #define JSON_HAS_CPP_11 #endif +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) #ifdef JSON_HAS_CPP_17 #if defined(__cpp_lib_filesystem) @@ -98,14 +104,37 @@ #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 + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L #define JSON_HAS_THREE_WAY_COMPARISON 1 #else #define JSON_HAS_THREE_WAY_COMPARISON 0 #endif #endif +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + // disable documentation warnings on clang #if defined(__clang__) #pragma clang diagnostic push @@ -423,3 +452,11 @@ #ifndef JSON_DIAGNOSTICS #define JSON_DIAGNOSTICS 0 #endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp index 377d3f11d..09f677b3d 100644 --- a/include/nlohmann/detail/macro_unscope.hpp +++ b/include/nlohmann/detail/macro_unscope.hpp @@ -14,6 +14,9 @@ #undef NLOHMANN_BASIC_JSON_TPL #undef JSON_EXPLICIT #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL +#undef JSON_INLINE_VARIABLE +#undef JSON_NO_UNIQUE_ADDRESS +#undef JSON_DISABLE_ENUM_SERIALIZATION #ifndef JSON_TEST_KEEP_MACROS #undef JSON_CATCH @@ -25,6 +28,8 @@ #undef JSON_HAS_FILESYSTEM #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM #undef JSON_HAS_THREE_WAY_COMPARISON + #undef JSON_HAS_RANGES + #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #endif #include diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 376c00a09..cc3483122 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -54,11 +54,6 @@ struct is_basic_json_context : || std::is_same::value > {}; -template struct is_json_pointer : std::false_type {}; - -template -struct is_json_pointer> : std::true_type {}; - ////////////////////// // json_ref helpers // ////////////////////// @@ -160,6 +155,24 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> T>::value; }; +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; /////////////////// // is_ functions // @@ -170,7 +183,7 @@ template struct conjunction : std::true_type { }; template struct conjunction : B { }; template struct conjunction -: std::conditional, B>::type {}; +: std::conditional(B::value), conjunction, B>::type {}; // https://en.cppreference.com/w/cpp/types/negation template struct negation : std::integral_constant < bool, !B::value > { }; @@ -334,8 +347,15 @@ struct is_compatible_string_type template struct is_constructible_string_type { + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + static constexpr auto value = - is_constructible::value; }; @@ -454,6 +474,78 @@ struct is_constructible_tuple : std::false_type {}; template struct is_constructible_tuple> : conjunction...> {}; +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template