diff --git a/.github/workflows/check_amalgamation.yml b/.github/workflows/check_amalgamation.yml index 0c30d5dea7..33f7822b36 100644 --- a/.github/workflows/check_amalgamation.yml +++ b/.github/workflows/check_amalgamation.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -20,7 +20,7 @@ jobs: mkdir -p ./pr echo ${{ github.event.number }} > ./pr/number echo ${{ github.event.pull_request.user.login }} > ./pr/author - - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: pr path: pr/ @@ -34,7 +34,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 15e15ca62f..e72d019ccb 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -28,7 +28,7 @@ jobs: dry-run: false language: c++ - name: Upload Crash - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7ece0dc661..1201a6458f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -36,14 +36,14 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: languages: c-cpp # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 diff --git a/.github/workflows/comment_check_amalgamation.yml b/.github/workflows/comment_check_amalgamation.yml index 708dc69a88..0ba4b8a8a5 100644 --- a/.github/workflows/comment_check_amalgamation.yml +++ b/.github/workflows/comment_check_amalgamation.yml @@ -19,12 +19,12 @@ jobs: pull-requests: write steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit - name: 'Download artifact' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -46,7 +46,7 @@ jobs: - run: unzip pr.zip - name: 'Comment on PR' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index a635b5f323..91df550fb5 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit - name: 'Checkout Repository' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 + uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 diff --git a/.github/workflows/flawfinder.yml b/.github/workflows/flawfinder.yml index 93f9cb007b..b88eb87fc6 100644 --- a/.github/workflows/flawfinder.yml +++ b/.github/workflows/flawfinder.yml @@ -27,7 +27,7 @@ jobs: security-events: write steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -35,12 +35,12 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: flawfinder_scan - uses: david-a-wheeler/flawfinder@c57197cd6061453f10a496f30a732bc1905918d1 # v2.0.19 + uses: david-a-wheeler/flawfinder@c4216b74cf2639ffa98503768bd6e4299b5440c9 # v2.0.20 with: arguments: '--sarif ./' output: 'flawfinder_results.sarif' - name: Upload analysis results to GitHub Security tab - uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4 + uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4 with: sarif_file: ${{github.workspace}}/flawfinder_results.sarif diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index a92becbca6..5662f02716 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit diff --git a/.github/workflows/publish_documentation.yml b/.github/workflows/publish_documentation.yml index bb2671a7c8..ad35ecfe21 100644 --- a/.github/workflows/publish_documentation.yml +++ b/.github/workflows/publish_documentation.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -40,7 +40,7 @@ jobs: run: make build -C docs/mkdocs - name: Deploy documentation - uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 + uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs/mkdocs/site diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index d36ef7c532..b6ea306848 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -68,7 +68,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: SARIF file path: results.sarif @@ -76,6 +76,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: sarif_file: results.sarif diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 2c694c4f3b..63f9cbf32e 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -48,7 +48,7 @@ jobs: # Upload SARIF file generated in previous step - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4 + uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4 with: sarif_file: semgrep.sarif if: always() diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b228e04494..5e1ad19096 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 4ff9134513..bf5fd9f1e7 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -46,7 +46,7 @@ jobs: target: [ci_test_amalgamation, ci_test_single_header, ci_cppcheck, ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_reuse_compliance, ci_test_valgrind] steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -54,7 +54,7 @@ jobs: run: sudo apt-get update ; sudo apt-get install -y valgrind - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -71,7 +71,7 @@ jobs: run: apt-get update ; apt-get install -y git clang-tools iwyu unzip - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -88,7 +88,7 @@ jobs: run: apt-get update ; apt-get install -y build-essential unzip wget git libssl-dev - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -98,7 +98,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit @@ -115,7 +115,7 @@ jobs: - name: Build run: cmake --build build --target ci_test_coverage - name: Archive coverage report - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: code-coverage-report path: ${{ github.workspace }}/build/html @@ -149,7 +149,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -164,7 +164,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Set env FORCE_STDCPPFS_FLAG for clang 7 / 8 / 9 / 10 run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV" if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }} @@ -182,7 +182,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -200,7 +200,7 @@ jobs: run: apt-get update ; apt-get install -y git unzip - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build with libc++ @@ -229,7 +229,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -251,15 +251,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit - name: Install emscripten - uses: mymindstorm/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14 + uses: mymindstorm/setup-emsdk@4528d102f7230f0e7b276855c01ea1159be0e984 # v16 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@f176ccd3f28bda569c43aae4894f06b2435a3375 # v4.2.3 + uses: lukka/get-cmake@7bfc9baacbbdcb5e37957ad05c3546b3e222be3c # v4.3.2 - name: Run CMake run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja - name: Build @@ -272,7 +272,7 @@ jobs: target: [ci_test_examples, ci_test_build_documentation] steps: - name: Harden Runner - uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 with: egress-policy: audit diff --git a/README.md b/README.md index 658f932202..97ac8f4516 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nl - [Martti Laine](https://github.com/codeclown) - [Paul Harrington](https://github.com/phrrngtn) - [Mercedes-Benz Group](https://github.com/mercedes-benz) +- [Ryan McCaffery](https://github.com/mccaffers) ### :label: Named Sponsors @@ -854,9 +855,9 @@ Some important things: #### Simplify your life with macros -If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate. There are [**several macros**](https://json.nlohmann.me/features/arbitrary_types/#simplify-your-life-with-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. +If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate. There are [**several macros**](https://json.nlohmann.me/api/macros/#serializationdeserialization-macros) to make your life easier as long as you want to use a JSON object as serialization. -Which macro to choose depends on whether private member variables need to be accessed, a deserialization is needed, missing values should yield an error or should be replaced by default values, and if derived classes are used. See [this overview to choose the right one for your use case](https://json.nlohmann.me/api/macros/#serializationdeserialization-macros). +Which macro to choose depends on whether private member variables need to be accessed, a deserialization is needed, missing values should yield an error or should be replaced by default values, and if derived classes are used. See [this overview to choose the right one for your use case](https://json.nlohmann.me/features/arbitrary_types/#simplify-your-life-with-macros). ##### Example usage of macros @@ -868,6 +869,18 @@ namespace ns { } ``` +If you want to inherit the `person` struct and add a field to it, it can be done with: + +```cpp +namespace ns { + struct person_derived : person { + std::string email; + }; + + NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(person_derived, person, email) +} +``` + Here is another example with private members, where [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/) is needed: ```cpp @@ -884,6 +897,24 @@ namespace ns { } ``` +Or in case if you use some naming convention that you do not want to expose to JSON: + +```cpp +namespace ns { + class address { + private: + std::string m_street; + int m_housenumber; + int m_postcode; + + public: + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(address, "street", m_street, + "housenumber", m_housenumber, + "postcode", m_postcode) + }; +} +``` + #### How do I convert third-party types? This requires a bit more advanced technique. But first, let's see how this conversion mechanism works: @@ -1074,7 +1105,7 @@ Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above, Other Important points: -- When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. +- When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. If you desire an exception in this circumstance use `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT()` which behaves identically except for throwing an exception on unrecognized values. - 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, UBJSON, and BJData) diff --git a/cmake/ci.cmake b/cmake/ci.cmake index f711368649..559ce8f55d 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -212,6 +212,21 @@ add_custom_target(ci_test_legacycomparison COMMENT "Compile and test with legacy discarded value comparison enabled" ) +############################################################################### +# Enable brace-init copy semantics. +############################################################################### + +add_custom_target(ci_test_brace_init_copy_semantics + COMMAND ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_FastTests=ON + -DCMAKE_CXX_FLAGS=-DJSON_BRACE_INIT_COPY_SEMANTICS=1 + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_brace_init_copy_semantics + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_brace_init_copy_semantics + COMMAND cd ${PROJECT_BINARY_DIR}/build_brace_init_copy_semantics && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMENT "Compile and test with brace-init copy semantics enabled" +) + ############################################################################### # Disable global UDLs. ############################################################################### diff --git a/cmake/requirements/requirements-cppcheck.txt b/cmake/requirements/requirements-cppcheck.txt index 9119ad7b6b..aa1591128d 100644 --- a/cmake/requirements/requirements-cppcheck.txt +++ b/cmake/requirements/requirements-cppcheck.txt @@ -1 +1 @@ -cppcheck==1.5.0 +cppcheck==1.5.1 diff --git a/docs/mkdocs/docs/api/basic_json/value.md b/docs/mkdocs/docs/api/basic_json/value.md index c9bca6be74..8b502c0154 100644 --- a/docs/mkdocs/docs/api/basic_json/value.md +++ b/docs/mkdocs/docs/api/basic_json/value.md @@ -110,7 +110,7 @@ changes to any JSON value. The value function is a template, and the return type of the function is determined by the type of the provided default value unless otherwise specified. This can have unexpected effects. In the example below, we store a 64-bit unsigned integer. We get exactly that value when using [`operator[]`](operator[].md). However, when we call `value` - and provide `#!c 0` as default value, then `#!c -1` is returned. The occurs, because `#!c 0` has type `#!c int` + and provide `#!c 0` as default value, then `#!c -1` is returned. This occurs, because `#!c 0` has type `#!c int` which overflows when handling the value `#!c 18446744073709551615`. To address this issue, either provide a correctly typed default value or use the template parameter to specify the diff --git a/docs/mkdocs/docs/api/json_pointer/front.md b/docs/mkdocs/docs/api/json_pointer/front.md new file mode 100644 index 0000000000..126f5ed903 --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/front.md @@ -0,0 +1,37 @@ +# nlohmann::json_pointer::front + +```cpp +const string_t& front() const; +``` + +Return the first reference token. + +## Return value + +First reference token. + +## Exceptions + +Throws [out_of_range.405](../../home/exceptions.md#jsonexceptionout_of_range405) if the JSON pointer has no parent. + +## Complexity + +Constant. + +## Examples + +??? example + + The example shows the usage of `front`. + + ```cpp + --8<-- "examples/json_pointer__front.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_pointer__front.output" + ``` + +## Version history diff --git a/docs/mkdocs/docs/api/json_pointer/index.md b/docs/mkdocs/docs/api/json_pointer/index.md index 8b70e2de71..b1f8953756 100644 --- a/docs/mkdocs/docs/api/json_pointer/index.md +++ b/docs/mkdocs/docs/api/json_pointer/index.md @@ -37,6 +37,9 @@ are the base for JSON patches. - [**pop_back**](pop_back.md) - remove the last reference token - [**back**](back.md) - return last reference token - [**push_back**](push_back.md) - append an unescaped token at the end of the pointer +- [**pop_front**](pop_front.md) - remove the first reference token +- [**front**](front.md) - return first reference token +- [**push_front**](push_front.md) - append an unescaped token at the start of the pointer - [**empty**](empty.md) - return whether the pointer points to the root document ## Literals diff --git a/docs/mkdocs/docs/api/json_pointer/pop_front.md b/docs/mkdocs/docs/api/json_pointer/pop_front.md new file mode 100644 index 0000000000..a0bfc546ae --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/pop_front.md @@ -0,0 +1,33 @@ +# nlohmann::json_pointer::pop_front + +```cpp +void pop_front(); +``` + +Remove the first reference token. + +## Exceptions + +Throws [out_of_range.405](../../home/exceptions.md#jsonexceptionout_of_range405) if the JSON pointer has no parent. + +## Complexity + +Linear in the number of reference tokens in the `json_pointer`. + +## Examples + +??? example + + The example shows the usage of `pop_front`. + + ```cpp + --8<-- "examples/json_pointer__pop_front.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_pointer__pop_front.output" + ``` + +## Version history diff --git a/docs/mkdocs/docs/api/json_pointer/push_front.md b/docs/mkdocs/docs/api/json_pointer/push_front.md new file mode 100644 index 0000000000..8d72f2363c --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/push_front.md @@ -0,0 +1,36 @@ +# nlohmann::json_pointer::push_front + +```cpp +void push_front(const string_t& token); + +void push_front(string_t&& token); +``` + +Append an unescaped token at the start of the reference pointer. + +## Parameters + +`token` (in) +: token to add + +## Complexity + +Linear in the number of reference tokens in the `json_pointer`. + +## Examples + +??? example + + The example shows the result of `push_front` for different JSON Pointers. + + ```cpp + --8<-- "examples/json_pointer__push_front.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_pointer__push_front.output" + ``` + +## Version history diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md index 59e4b3d280..2397bc7024 100644 --- a/docs/mkdocs/docs/api/macros/index.md +++ b/docs/mkdocs/docs/api/macros/index.md @@ -40,6 +40,7 @@ header. See also the [macro overview page](../../features/macros.md). ## Type conversions +- [**JSON_BRACE_INIT_COPY_SEMANTICS**](json_brace_init_copy_semantics.md) - opt in to copy/move semantics for single-element brace initialization - [**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 @@ -53,6 +54,7 @@ header. See also the [macro overview page](../../features/macros.md). ### Enums - [**NLOHMANN_JSON_SERIALIZE_ENUM**](nlohmann_json_serialize_enum.md) - serialize/deserialize an enum +- [**NLOHMANN_JSON_SERIALIZE_ENUM_STRICT**](nlohmann_json_serialize_enum_strict.md) - serialize/deserialize an enum with exceptions ### Classes and structs @@ -81,3 +83,28 @@ header. See also the [macro overview page](../../features/macros.md). a derived class; uses default values - [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE**](nlohmann_define_derived_type.md) - serialize a derived class +- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize a non-derived class + with private members; uses custom names +- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize a + non-derived class with private members; uses default values; uses custom names +- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize a non-derived class + with private members; uses custom names +- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize a non-derived + class; uses custom names +- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize a + non-derived class; uses default values; uses custom names +- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize a + non-derived class; uses custom names + +- [**NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize a derived class + with private members; uses custom names +- [**NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize a + derived class with private members; uses default values; uses custom names +- [**NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize a derived + class with private members; uses custom names +- [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize a derived + class; uses custom names +- [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize + a derived class; uses default values; uses custom names +- [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize a derived + class; uses custom names \ No newline at end of file diff --git a/docs/mkdocs/docs/api/macros/json_brace_init_copy_semantics.md b/docs/mkdocs/docs/api/macros/json_brace_init_copy_semantics.md new file mode 100644 index 0000000000..8d88acf473 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_brace_init_copy_semantics.md @@ -0,0 +1,95 @@ +# JSON_BRACE_INIT_COPY_SEMANTICS + +```cpp +#define JSON_BRACE_INIT_COPY_SEMANTICS /* value */ +``` + +When defined to `1`, single-element brace initialization of a `basic_json` value is treated as a copy/move of the +element rather than wrapping it in a single-element array. + +## Default definition + +The default value is `0` (disabled — existing behavior is preserved). + +```cpp +#define JSON_BRACE_INIT_COPY_SEMANTICS 0 +``` + +## Notes + +!!! note "Background" + + C++ always prefers the `initializer_list` constructor over the copy/move constructor for brace initialization. This + means that code like + + ```cpp + json obj = {{"key", "value"}}; + json j{obj}; + ``` + + creates a single-element **array** `[{"key":"value"}]` instead of a copy of `obj`. This behavior is + compiler-dependent for older compilers (GCC wrapped, Clang did not), but starting from Clang 20, both compilers + behave the same way. + + Enabling this macro opts into copy/move semantics for this case + (see [#5074](https://github.com/nlohmann/json/issues/5074)). + +!!! warning "Opt-in only" + + This macro must be defined **before** including ``. Defining it after the include has no effect. + +!!! tip "Workaround without the macro" + + To explicitly create a single-element array without enabling this macro, use `json::array()`: + + ```cpp + json j = json::array({obj}); // always creates [obj] + ``` + +## Examples + +??? example "Default behavior (macro not defined)" + + Without the macro, single-element brace initialization wraps the value in an array: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + json obj = {{"key", "value"}}; + + json j{obj}; + // j is [{"key":"value"}] -- single-element array, NOT a copy of obj + } + ``` + +??? example "Opt-in copy semantics (macro defined to 1)" + + With the macro, single-element brace initialization copies/moves the value: + + ```cpp + #define JSON_BRACE_INIT_COPY_SEMANTICS 1 + #include + + using json = nlohmann::json; + + int main() + { + json obj = {{"key", "value"}}; + + json j{obj}; + // j is {"key":"value"} -- copy of obj + } + ``` + +## See also + +- [FAQ: Brace initialization yields arrays](../../home/faq.md#brace-initialization-yields-arrays) +- [**basic_json(initializer_list_t)**](../basic_json/basic_json.md) - the affected constructor + +## Version history + +- Added in version 3.12.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_define_derived_type.md b/docs/mkdocs/docs/api/macros/nlohmann_define_derived_type.md index d33bc1eebd..0d20566194 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_define_derived_type.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_derived_type.md @@ -57,7 +57,7 @@ Summary: : name of the base type (class, struct) `type` is derived from `member` (in) -: name of the member variable to serialize/deserialize; up to 64 members can be given as a comma-separated list +: name of the member variable to serialize/deserialize; up to 63 members can be given as a comma-separated list ## Default definition diff --git a/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md index b95d26799b..629ae2522c 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md @@ -33,7 +33,7 @@ Summary: : 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 a comma-separated list +: name of the member variable to serialize/deserialize; up to 63 members can be given as a comma-separated list ## Default definition @@ -60,8 +60,8 @@ See the examples below for the concrete generated code. !!! 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 current implementation is limited to at most 63 member variables. If you want to serialize/deserialize types + with more than 63 member variables, you need to define the `to_json`/`from_json` functions manually. ## Examples 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 index c3e2721c0d..7feb8dbe33 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md @@ -33,7 +33,7 @@ Summary: : 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 a comma-separated list +: name of the (public) member variable to serialize/deserialize; up to 63 members can be given as a comma-separated list ## Default definition @@ -61,8 +61,8 @@ See the examples below for the concrete generated code. !!! 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 current implementation is limited to at most 63 member variables. If you want to serialize/deserialize types + with more than 63 member variables, you need to define the `to_json`/`from_json` functions manually. ## Examples diff --git a/docs/mkdocs/docs/api/macros/nlohmann_define_type_with_names.md b/docs/mkdocs/docs/api/macros/nlohmann_define_type_with_names.md new file mode 100644 index 0000000000..798be4b80b --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_with_names.md @@ -0,0 +1,78 @@ +

NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, + NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES, + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES, + NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES

+ +```cpp +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(type, "json_member_name", member...) +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, "json_member_name", member...) +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, "json_member_name", member...) +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES(type, "json_member_name", member...) +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, "json_member_name", member...) +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, "json_member_name", member...) +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES(type, base_type, "json_member_name", member...) +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, base_type, "json_member_name", member...) +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, base_type, "json_member_name", member...) +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES(type, base_type, "json_member_name", member...) +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, base_type, "json_member_name", member...) +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, base_type, "json_member_name", member...) +``` + +These macros can be used in case you want to use the custom names for the member variables in the resulting JSON. +They behave exactly as their non-`WITH_NAMES` counterparts, but require an additional parameter for each member variable +which will be used in JSON. Both serialization and deserialization will only use the custom names for JSON, the names of +the member variables themselves will be ignored. + +Using the named conversion macros will halve the maximum number of member variables from 63 to 31. + +For further information please refer to the corresponding macros without `WITH_NAMES`. + +## Parameters + +`type` (in) +: name of the type (class, struct) to serialize/deserialize + +`base_type` (in) +: name of the base type (class, struct) `type` is derived from (used only in `DEFINE_DERIVED_TYPE` macros) + +`json_member_name` (in) +: the string that will be used as the name for the next value + +`member` (in) +: name of the member variable to serialize/deserialize + +## Examples + +??? example "Example (1): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES" + + Consider the following complete example: + + ```cpp hl_lines="16" + --8<-- "examples/nlohmann_define_type_non_intrusive_with_names_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_non_intrusive_with_names_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_NAMES` applicable. + - The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES` 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_WITH_NAMES` can be used. + + The macro is equivalent to: + + ```cpp hl_lines="16 17 18 19 20 21 22 23 24 25 26 27 28" + --8<-- "examples/nlohmann_define_type_non_intrusive_with_names_explicit.cpp" + ``` + +## Version history + +1. Added in version 3.11.x. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md index fba6b217ab..915a20a5f5 100644 --- a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md @@ -78,6 +78,7 @@ inline void from_json(const BasicJsonType& j, type& e); ## See also - [Specializing enum conversion](../../features/enum_conversion.md) +- [`NLOHMANN_JSON_SERIALIZE_ENUM_STRICT`](./nlohmann_json_serialize_enum_strict.md) - [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) ## Version history diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum_strict.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum_strict.md new file mode 100644 index 0000000000..f4c52e0706 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum_strict.md @@ -0,0 +1,102 @@ +# NLOHMANN_JSON_SERIALIZE_ENUM_STRICT + +```cpp +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(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 deserialized JSON data may be +undefined or a different enum value than was originally intended. + +`NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` allows to define a user-defined serialization for every enumerator that +throws an exception on undefined input. + +## Parameters + +`type` (in) +: name of the enum to serialize/deserialize + +`conversion` (in) +: a pair of an enumerator and a JSON serialization; arbitrary pairs can be given as a comma-separated list + +## Default definition + +The macro adds two functions to the namespace 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 throw an exception. + - 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_STRICT` 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_strict.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_serialize_enum_strict.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_strict_2.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_serialize_enum_strict_2.output" + ``` + +??? example "Example 3: exceptions on invalid serialization" + + The example shows how an invalid serialization causes an exception to be thrown. In the example, + Color::unknown is not defined in the mapping used to call `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` + so causes an exception when used to serialize. Similarly, "what" does not refer to an enum + value so also causes an exception when deserialization is attempted. + + ```cpp hl_lines="14 32 33 43 44 45" + --8<-- "examples/nlohmann_json_serialize_enum_strict_err.cpp" + ``` + + Output: + ```json + --8<-- "examples/nlohmann_json_serialize_enum_strict_err.output" + ``` + +## See also + +- [Specializing enum conversion](../../features/enum_conversion.md) +- [`NLOHMANN_JSON_SERIALIZE_ENUM`](./nlohmann_json_serialize_enum.md) +- [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) + +## Version history + +Added in version 3.12.0. diff --git a/docs/mkdocs/docs/examples/json_pointer__front.cpp b/docs/mkdocs/docs/examples/json_pointer__front.cpp new file mode 100644 index 0000000000..42c76ffec3 --- /dev/null +++ b/docs/mkdocs/docs/examples/json_pointer__front.cpp @@ -0,0 +1,15 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON Pointers + json::json_pointer ptr1("/foo"); + json::json_pointer ptr2("/foo/0"); + + // call empty() + std::cout << "first reference token of \"" << ptr1 << "\" is \"" << ptr1.front() << "\"\n" + << "first reference token of \"" << ptr2 << "\" is \"" << ptr2.front() << "\"" << std::endl; +} diff --git a/docs/mkdocs/docs/examples/json_pointer__front.output b/docs/mkdocs/docs/examples/json_pointer__front.output new file mode 100644 index 0000000000..f7a5adc808 --- /dev/null +++ b/docs/mkdocs/docs/examples/json_pointer__front.output @@ -0,0 +1,2 @@ +first reference token of "/foo" is "foo" +first reference token of "/foo/0" is "foo" diff --git a/docs/mkdocs/docs/examples/json_pointer__pop_front.cpp b/docs/mkdocs/docs/examples/json_pointer__pop_front.cpp new file mode 100644 index 0000000000..59403668cf --- /dev/null +++ b/docs/mkdocs/docs/examples/json_pointer__pop_front.cpp @@ -0,0 +1,21 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create empty JSON Pointer + json::json_pointer ptr("/foo/bar/baz"); + std::cout << "\"" << ptr << "\"\n"; + + // call pop_front() + ptr.pop_front(); + std::cout << "\"" << ptr << "\"\n"; + + ptr.pop_front(); + std::cout << "\"" << ptr << "\"\n"; + + ptr.pop_front(); + std::cout << "\"" << ptr << "\"\n"; +} diff --git a/docs/mkdocs/docs/examples/json_pointer__pop_front.output b/docs/mkdocs/docs/examples/json_pointer__pop_front.output new file mode 100644 index 0000000000..73d81b9535 --- /dev/null +++ b/docs/mkdocs/docs/examples/json_pointer__pop_front.output @@ -0,0 +1,4 @@ +"/foo/bar/baz" +"/bar/baz" +"/baz" +"" diff --git a/docs/mkdocs/docs/examples/json_pointer__push_front.cpp b/docs/mkdocs/docs/examples/json_pointer__push_front.cpp new file mode 100644 index 0000000000..7bcdccb452 --- /dev/null +++ b/docs/mkdocs/docs/examples/json_pointer__push_front.cpp @@ -0,0 +1,21 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create empty JSON Pointer + json::json_pointer ptr; + std::cout << "\"" << ptr << "\"\n"; + + // call push_front() + ptr.push_front("foo"); + std::cout << "\"" << ptr << "\"\n"; + + ptr.push_front("0"); + std::cout << "\"" << ptr << "\"\n"; + + ptr.push_front("bar"); + std::cout << "\"" << ptr << "\"\n"; +} diff --git a/docs/mkdocs/docs/examples/json_pointer__push_front.output b/docs/mkdocs/docs/examples/json_pointer__push_front.output new file mode 100644 index 0000000000..79bf849468 --- /dev/null +++ b/docs/mkdocs/docs/examples/json_pointer__push_front.output @@ -0,0 +1,4 @@ +"" +"/foo" +"/0/foo" +"/bar/0/foo" diff --git a/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_explicit.cpp b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_explicit.cpp new file mode 100644 index 0000000000..d92f13c42d --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_explicit.cpp @@ -0,0 +1,55 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +struct person +{ + std::string name; + std::string address; + int age; +}; + +template ::value, int> = 0> +void to_json(BasicJsonType& nlohmann_json_j, const person& nlohmann_json_t) +{ + nlohmann_json_j["json_name"] = nlohmann_json_t.name; + nlohmann_json_j["json_address"] = nlohmann_json_t.address; + nlohmann_json_j["json_age"] = nlohmann_json_t.age; +} + +template ::value, int> = 0> +void from_json(const BasicJsonType& nlohmann_json_j, person& nlohmann_json_t) +{ + nlohmann_json_j.at("json_name").get_to(nlohmann_json_t.name); + nlohmann_json_j.at("json_address").get_to(nlohmann_json_t.address); + nlohmann_json_j.at("json_age").get_to(nlohmann_json_t.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"({"json_address": "742 Evergreen Terrace", "json_age": 40, "json_name": "Homer Simpson"})"_json; + auto p2 = j2.template get(); + + // incomplete deserialization: + json j3 = R"({"json_address": "742 Evergreen Terrace", "json_name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.template get(); + } + catch (const json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_explicit.output b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_explicit.output new file mode 100644 index 0000000000..c4a689b3f8 --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_explicit.output @@ -0,0 +1,2 @@ +serialization: {"json_address":"744 Evergreen Terrace","json_age":60,"json_name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'json_age' not found diff --git a/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_macro.cpp b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_macro.cpp new file mode 100644 index 0000000000..36114e724b --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_macro.cpp @@ -0,0 +1,41 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +struct person +{ + std::string name; + std::string address; + int age; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES(person, "json_name", name, "json_address", address, "json_age", 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"({"json_address": "742 Evergreen Terrace", "json_age": 40, "json_name": "Homer Simpson"})"_json; + auto p2 = j2.template get(); + + // incomplete deserialization: + json j3 = R"({"json_address": "742 Evergreen Terrace", "json_name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.template get(); + } + catch (const json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_macro.output b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_macro.output new file mode 100644 index 0000000000..c4a689b3f8 --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_define_type_non_intrusive_with_names_macro.output @@ -0,0 +1,2 @@ +serialization: {"json_address":"744 Evergreen Terrace","json_age":60,"json_name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'json_age' not found diff --git a/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict.cpp b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict.cpp new file mode 100644 index 0000000000..fa2572dec1 --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict.cpp @@ -0,0 +1,52 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +enum TaskState +{ + TS_STOPPED, + TS_RUNNING, + TS_COMPLETED, + TS_INVALID = -1 +}; + +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(TaskState, +{ + { TS_INVALID, nullptr }, + { TS_STOPPED, "stopped" }, + { TS_RUNNING, "running" }, + { TS_COMPLETED, "completed" } +}) + +enum class Color +{ + red, green, blue, unknown +}; + +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(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; + +} diff --git a/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict.output b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict.output new file mode 100644 index 0000000000..59c4ff70ab --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict.output @@ -0,0 +1,2 @@ +ns::TS_STOPPED -> "stopped", ns::Color::red -> "red" +"running" -> 1, "blue" -> 2 diff --git a/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_2.cpp b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_2.cpp new file mode 100644 index 0000000000..7f766b7a93 --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_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_STRICT(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/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_2.output b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_2.output new file mode 100644 index 0000000000..5dec31b4ad --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_2.output @@ -0,0 +1,3 @@ +0 -> "red" +"rot" -> 0 +"red" -> 0 diff --git a/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_err.cpp b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_err.cpp new file mode 100644 index 0000000000..aeb9011228 --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_err.cpp @@ -0,0 +1,53 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ + +enum class Color +{ + red, + green, + blue, + unknown // not mapped in JSON_SERIALIZE_ENUM_STRICT +}; + +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(Color, +{ + {Color::red, "red"}, + {Color::green, "green"}, + {Color::blue, "blue"} +}) + +} // namespace ns + + +int main() +{ + // invalid serialization + try + { + // ns::color::unknown was not mapped in macro + json invalid_serialization = ns::Color::unknown; + } + catch (const json::exception e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } + + // invalid deserialization + try + { + // what does not map to an enum + json invalid_deserialization("what"); + ns::Color color = invalid_deserialization.get(); + } + catch (const json::exception e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } + + return 0; +} diff --git a/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_err.output b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_err.output new file mode 100644 index 0000000000..4894b4c7d2 --- /dev/null +++ b/docs/mkdocs/docs/examples/nlohmann_json_serialize_enum_strict_err.output @@ -0,0 +1,2 @@ +deserialization failed: [json.exception.out_of_range.410] enum value out of range for Color +deserialization failed: [json.exception.out_of_range.410] enum value out of range for Color: "what" diff --git a/docs/mkdocs/docs/features/arbitrary_types.md b/docs/mkdocs/docs/features/arbitrary_types.md index 1e79bfec28..1efb4be15a 100644 --- a/docs/mkdocs/docs/features/arbitrary_types.md +++ b/docs/mkdocs/docs/features/arbitrary_types.md @@ -85,16 +85,18 @@ Some important things: If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate. -There are six macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object: +There are several macros to make your life easier as long as you want to use a JSON object as serialization. The macros are following the naming pattern, and you can chose the macro based on the needed features: -- [`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 an object which is default-constructed by the type. -- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(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 does not define a `from_json()` function which is needed in case the type does not have a default constructor. -- [`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 an object which is default-constructed by the type. -- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(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 does not define a `from_json()` function which is needed in case the type does not have a default constructor. +- All the macros start with `NLOHMANN_DEFINE`. +- If you want a macro for the derived object, use the [`DERIVED_TYPE`](../api/macros/nlohmann_define_derived_type.md) variant, otherwise use `TYPE`. + - The `DERIVED_TYPE` variant requires an additional parameter of a base type, which should have the `to_json`/`from_json` functions defined. For instance, with a macro of its own. +- If you need access to the private fields use [`INTRUSIVE`](../api/macros/nlohmann_define_type_intrusive.md) variant, otherwise use [`NON_INTRUSIVE`](../api/macros/nlohmann_define_type_non_intrusive.md). + - The `INTRUSIVE` macro should be defined **inside** the target class/struct, `NON_INTRUSIVE` should be defined within the same namespace. +- If you want to deserialize the incomplete JSONs, use the `WITH_DEFAULTS` variant, which will use the default values for the member variables absent in JSON, the variant without `WITH_DEFAULTS` will raise an exception. +- If you do not need deserialization at all and only interested in `to_json` function, you can use the `ONLY_SERIALIZE` variant. +- If you want to use the custom JSON names for member variables, use [`WITH_NAMES`](../api/macros/nlohmann_define_type_with_names.md) variant, otherwise the JSON name of the variable will be the same as its regular name. -Furthermore, there exist versions to use in the case of derived classes: +For all the macros, the first parameter is the name of the class/struct. The `DERIVED_TYPE` macros require a second parameter of a base class. All the remaining parameters name the member variables. The `WITH_NAMES` macros require a JSON name before each of the variables. | Need access to private members | Need only de-serialization | Allow missing values when de-serializing | macro | |------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| @@ -118,8 +120,9 @@ For _derived_ classes and structs, use the following macros !!! info "Implementation limits" - - 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 current macro implementations are limited to at most 63 member variables. If you want to serialize/deserialize + types with more than 63 member variables, you need to define the `to_json`/`from_json` functions manually. + - For the `WITH_NAMES` variants the limit is halved to 31 member variables. ??? example @@ -131,8 +134,20 @@ For _derived_ classes and structs, use the following macros } ``` - Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed: - + If you want to inherit the `person` struct and add a field to it, it can be done with: + + ```cpp + namespace ns { + struct person_derived : person { + std:string email; + }; + + NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(person_derived, person, email) + } + ``` + + Here is another example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed: + ```cpp namespace ns { class address { @@ -140,12 +155,30 @@ For _derived_ classes and structs, use the following macros std::string street; int housenumber; int postcode; - + public: NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode) }; } ``` + + Or in case if you use some naming convention that you do not want to expose to JSON: + + ```cpp + namespace ns { + class address { + private: + std::string m_street; + int m_housenumber; + int m_postcode; + + public: + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(address, "street", m_street, + "housenumber", m_housenumber, + "postcode", m_postcode) + }; + } + ``` ## How do I convert third-party types? diff --git a/docs/mkdocs/docs/features/enum_conversion.md b/docs/mkdocs/docs/features/enum_conversion.md index bd3977d919..d75d6e1121 100644 --- a/docs/mkdocs/docs/features/enum_conversion.md +++ b/docs/mkdocs/docs/features/enum_conversion.md @@ -55,7 +55,8 @@ Just as in [Arbitrary Type Conversions](arbitrary_types.md) above, Other Important points: - When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this - default pair carefully. + default pair carefully. If you desire an exception in this circumstance use [`NLOHMANN_JSON_SERIALIZE_ENUM_STRICT()`](../api/macros/nlohmann_json_serialize_enum_strict.md) + which behaves identically except for throwing an exception on unrecognized values. - 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/docs/mkdocs/docs/features/modules.md b/docs/mkdocs/docs/features/modules.md index 6068108b8b..6574a92218 100644 --- a/docs/mkdocs/docs/features/modules.md +++ b/docs/mkdocs/docs/features/modules.md @@ -24,11 +24,21 @@ json data = json::parse(f); ``` ## Modules do not export macros -It should be noted that as modules do not export macros, the `nlohmann.json` module will not export any macros, but rather only the following symbols: +It should be noted that as modules do not export macros, the `nlohmann.json` module will not export any macros. +## Exported symbols +Only the following symbols are exported from `nlohmann.json`: - `nlohmann::adl_serializer` - `nlohmann::basic_json` - `nlohmann::json` - `nlohmann::json_pointer` -- `nlohmann::ordered_map` - `nlohmann::ordered_json` +- `nlohmann::ordered_map` +- `nlohmann::to_string` +- `nlohmann::literals::json_literals::operator""_json` +- `nlohmann::literals::json_literals::operator""_json_pointer` + +The following specialisations of `std` symbols are also exported: +- `std::hash` +- `std::less` +- `std::swap` diff --git a/docs/mkdocs/docs/home/exceptions.md b/docs/mkdocs/docs/home/exceptions.md index 30487348ee..c949bdbf28 100644 --- a/docs/mkdocs/docs/home/exceptions.md +++ b/docs/mkdocs/docs/home/exceptions.md @@ -868,6 +868,16 @@ Key identifiers to be serialized to BSON cannot contain code point U+0000, since BSON key cannot contain code point U+0000 (at byte 2) ``` +### json.exception.out_of_range.410 + +Undefined json fields cannot be used with [`NLOHMANN_JSON_SERIALIZE_ENUM_STRICT`](../api/macros/nlohmann_json_serialize_enum_strict.md) + +!!! failure "Example message" + + ``` + enum value out of range + ``` + ## Further exceptions This exception is thrown in case of errors that cannot be classified with the @@ -900,13 +910,3 @@ A JSON Patch operation 'test' failed. The unsuccessful operation is also printed ``` [json.exception.other_error.501] unsuccessful: {"op":"test","path":"/baz","value":"bar"} ``` - -### json.exception.other_error.502 - -This exception is thrown when a null pointer is passed as SAX event listener to the [sax_parse](../api/basic_json/sax_parse.md) function. - -!!! failure "Example message" - - ``` - [json.exception.other_error.502] SAX handler must not be null - ``` diff --git a/docs/mkdocs/docs/home/faq.md b/docs/mkdocs/docs/home/faq.md index 74709bac68..92cc935810 100644 --- a/docs/mkdocs/docs/home/faq.md +++ b/docs/mkdocs/docs/home/faq.md @@ -38,6 +38,26 @@ for objects. To avoid any confusion and ensure portable code, **do not** use brace initialization with the types `basic_json`, `json`, or `ordered_json` unless you want to create an object or array as shown in the examples above. + To explicitly create a single-element array, use `json::array({value})`: + + ```cpp + json j = json::array({true}); // [true] + ``` + +**Opt-in copy semantics (since version 3.12.0)** + +If you define `JSON_BRACE_INIT_COPY_SEMANTICS` to `1` before including the library, single-element brace initialization is treated as copy/move instead of creating a single-element array: + +```cpp +#define JSON_BRACE_INIT_COPY_SEMANTICS 1 +#include + +json obj = {{"key", "value"}}; +json j{obj}; // -> {"key":"value"} (copy, not array) +``` + +Without the macro (default behavior), `json j{obj}` creates `[{"key":"value"}]`. This opt-in macro fixes issue #5074 while preserving backwards compatibility for existing code. + ## Limitations ### Relaxed parsing diff --git a/docs/mkdocs/docs/integration/build2/buildfile b/docs/mkdocs/docs/integration/build2/buildfile new file mode 100644 index 0000000000..f91000373c --- /dev/null +++ b/docs/mkdocs/docs/integration/build2/buildfile @@ -0,0 +1,6 @@ +libs = +import libs = nlohmann-json%lib{json} + +exe{example}: {hxx ixx txx cxx}{**} $libs testscript + +cxx.poptions =+ "-I$out_root" "-I$src_root" diff --git a/docs/mkdocs/docs/integration/build2/example.cpp b/docs/mkdocs/docs/integration/build2/example.cpp new file mode 100644 index 0000000000..1a7ac4de2e --- /dev/null +++ b/docs/mkdocs/docs/integration/build2/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/docs/mkdocs/docs/integration/build2/manifest b/docs/mkdocs/docs/integration/build2/manifest new file mode 100644 index 0000000000..5ff2a90486 --- /dev/null +++ b/docs/mkdocs/docs/integration/build2/manifest @@ -0,0 +1,14 @@ +name: example +version: 0.1.0-a.0.z +language: c++ +summary: example C++ executable +license: other: proprietary ; Not free/open source. +description-file: README.md +url: https://example.org/example +email: your@emailprovider.com +#build-error-email: your@emailprovider.com +depends: * build2 >= 0.16.0 +depends: * bpkg >= 0.16.0 +#depends: libhello ^1.0.0 + +depends: nlohmann-json diff --git a/docs/mkdocs/docs/integration/build2/repositories.manifest b/docs/mkdocs/docs/integration/build2/repositories.manifest new file mode 100644 index 0000000000..18cf7b620f --- /dev/null +++ b/docs/mkdocs/docs/integration/build2/repositories.manifest @@ -0,0 +1,11 @@ +: 1 +summary: example project repository + +: +role: prerequisite +location: https://pkg.cppget.org/1/stable +#trust: ... + +#: +#role: prerequisite +#location: https://git.build2.org/hello/libhello.git diff --git a/docs/mkdocs/docs/integration/build2/testscript b/docs/mkdocs/docs/integration/build2/testscript new file mode 100644 index 0000000000..963c4e6713 --- /dev/null +++ b/docs/mkdocs/docs/integration/build2/testscript @@ -0,0 +1,24 @@ + +: json basics +: +$* >>~/EOO/ +{ + "compiler": { +/ "c\+\+": "\d+",/ +/ "family": "[\w\d]+",/ +/ "version": \d+/ + }, +/ "copyright": "\(C\) 2013-\d+ Niels Lohmann",/ + "name": "JSON for Modern C++", +/ "platform": "[\w\d]+",/ + "url": "https://github.com/nlohmann/json", + "version": { + "major": 3, +/ "minor": \d+,/ +/ "patch": \d+,/ +/ "string": "3\.\d+\.\d+"/ + } +} +EOO + + diff --git a/docs/mkdocs/docs/integration/package_managers.md b/docs/mkdocs/docs/integration/package_managers.md index 9d62c05d53..0160f48a34 100644 --- a/docs/mkdocs/docs/integration/package_managers.md +++ b/docs/mkdocs/docs/integration/package_managers.md @@ -464,7 +464,7 @@ dotnet add package nlohmann.json ??? example - Probably the easiest way to use NuGet packages is through Visual Studio graphical interface. Just right-click on a + Probably the easiest way to use NuGet packages is through Visual Studio graphical interface. Right-click on a project (any C++ project would do) in “Solution Explorer” and select “Manage NuGet Packages…” ![](nuget/nuget-search-package.png) @@ -700,17 +700,128 @@ to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) p ## build2 -If you are using [`build2`](https://build2.org), you can use the [`nlohmann-json`](https://cppget.org/nlohmann-json) -package from the public repository or directly from the -[package's sources repository](https://github.com/build2-packaging/nlohmann-json). In your project's `manifest` file, -add `depends: nlohmann-json` (probably with some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps)). If you are not familiar with using dependencies in `build2`, [please read this introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml). -Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if you experience problems with the packages. +!!! abstract "Summary" -:material-update: The [package](https://cppget.org/nlohmann-json) is updated automatically. + package: **`nlohmann-json`** + library target: **`nlohmann-json%lib{json}`** + available in package repositories: + - [`cppget.org` (recommended)](https://cppget.org/nlohmann-json) + - [package's sources (for advanced users)](https://github.com/build2-packaging/nlohmann-json/) -```shell -bdep new -t exe -l c++ -``` + - :octicons-tag-24: Available versions: current version and older versions since `3.7.3` (see [cppget.org](https://cppget.org/nlohmann-json)) + - :octicons-rocket-24: The package is maintained and published by the `build2` community in [this repository][(https://github.com/build2-packaging/nlohmann-json/](https://github.com/build2-packaging/nlohmann-json/)). + - :octicons-file-24: File issues at the [package source repository](https://github.com/build2-packaging/nlohmann-json/issues/) + - :octicons-question-24: [`build2` website](https://build2) + +Note: [`build2`](https://build2.org) should not be considered as a standalone package-manager. It is a build-system + package manager + project manager, a set of tools that work hand-in-hand. `build2`-based projects do not rely on existing `CMake` scripts and the build scripts defining the project's targets are specific to `build2`. + +To use this package in an exising [`build2`](https://build2.org) project, the general steps are: + + 1.
Make the package available to download from a package repository that provides it. + + Your project's `repositories.manifest` specifies where the package manager will try to acquire packages by default. Make sure one of the repositories specified in this file provides `nlhomann-json` package. + The recommended open-source repository is [`cppget.org`](https://cppget.org/). + + If the project has been created using [`bdep new`](https://build2.org/bdep/doc/bdep-new.xhtml), `cppget.org` is already specified in `repositories.manifest` but commented, just uncomment these lines: + ``` + : + role: prerequisite + location: https://pkg.cppget.org/1/stable + ``` +
+ + 2.
Add this package as dependency of your project. + + In your project's `manifest` add the dependency to the package using `depends: nlohmann-json`. You could also add some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps). + For example, to depend on the latest version available: + ``` + depends: nlohmann-json + ``` +
+ + + 2.
Add this library as dependency of your target that uses it. + + In the `buildfile` defining the target that will use this library: + + - import the target `lib{json}` from the `nlhomann-json` package, for example: + ``` + import nljson = nlhomann-json%lib{json} + ``` + + - then add the library's target as requirement for your target using it, for example: + ``` + exe{example} : ... $nljson + ``` + +
+ + 3.
Use the library in your project's code and build it. + + At this point, assuming your project is initialized in a build-configuration, any `b` or `bdep update` command that will update/build the project will also acquire the missing dependency automatically, then build it and link it with your target. + + If you just want to synchronize dependencies for all your configurations to download the ones you just added: + ``` + bdep sync -af + ``` +
+ +??? example "Example: from scratch, using `build2`'s [`bdep new` command](https://build2.org/bdep/doc/bdep-new.xhtml)" + + 1. Create a new executable project "example" (see [`bdep new` command details](https://build2.org/bdep/doc/bdep-new.xhtml) for the various options to create a new project): + + ```shell + bdep new example + ``` + + 2. Edit these files by replacing their content: + + - `example/repositories.manifest`: Enable acquiring packages from https://cppget.org by uncommenting the related lines: + + ```make title="project's `repositories.manifest`" + --8<-- "integration/build2/repositories.manifest" + ``` + + - `example/manifest`: Add the latest version of the `nlohmann-json` package as dependency to the project: + + ```make title="project's `manifest`" + --8<-- "integration/build2/manifest" + ``` + + - `example/example/buildfile`: import the library's target to be used as requirement for building the executable target `exe{example}`: + + ```make title="project's `buildfile`" + --8<-- "integration/build2/buildfile" + ``` + + - `example/example/example.cxx`: `bdep new` generates a "hello world" by default, replace it by this: + + ```cpp title="example.cxx" + --8<-- "integration/build2/example.cpp" + ``` + + - `example/example/testscript`: (optional) if you want to be able to test that executable's output is correct using `b test`: + + ```cpp title="`testscript` checking the output of the program" + --8<-- "integration/build2/testscript" + ``` + + + 3. Initialize the project in a default C/C++ build configuration directory, then build and test: + + ```shell + cd example/ + + # create default C/C++ build configuration in ../example-myconfig/, initialize the project in it (downloads it's dependencies in it too) + bdep init -C @myconfig cc + + # build only, + b + + # or build and test the executable's output, will only work if the `tescript` is correct + b test + + ``` ## CPM.cmake diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index ea089c7ea5..c374926d2d 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -233,6 +233,7 @@ nav: - '(Constructor)': api/json_pointer/json_pointer.md - 'back': api/json_pointer/back.md - 'empty': api/json_pointer/empty.md + - 'front': api/json_pointer/front.md - 'operator string_t': api/json_pointer/operator_string_t.md - 'operator==': api/json_pointer/operator_eq.md - 'operator!=': api/json_pointer/operator_ne.md @@ -240,7 +241,9 @@ nav: - 'operator/=': api/json_pointer/operator_slasheq.md - 'parent_pointer': api/json_pointer/parent_pointer.md - 'pop_back': api/json_pointer/pop_back.md + - 'pop_front': api/json_pointer/pop_front.md - 'push_back': api/json_pointer/push_back.md + - 'push_front': api/json_pointer/push_front.md - 'string_t': api/json_pointer/string_t.md - 'to_string': api/json_pointer/to_string.md - json_sax: @@ -286,10 +289,12 @@ nav: - 'NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_derived_type.md - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_type_intrusive.md - 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_type_non_intrusive.md + - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES': api/macros/nlohmann_define_type_with_names.md - 'NLOHMANN_JSON_NAMESPACE': api/macros/nlohmann_json_namespace.md - 'NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END': api/macros/nlohmann_json_namespace_begin.md - 'NLOHMANN_JSON_NAMESPACE_NO_VERSION': api/macros/nlohmann_json_namespace_no_version.md - 'NLOHMANN_JSON_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.md + - 'NLOHMANN_JSON_SERIALIZE_ENUM_STRICT': api/macros/nlohmann_json_serialize_enum_strict.md - 'NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH': api/macros/nlohmann_json_version_major.md - Community: - community/index.md diff --git a/docs/mkdocs/requirements.txt b/docs/mkdocs/requirements.txt index 31d572f126..ff684cbd00 100644 --- a/docs/mkdocs/requirements.txt +++ b/docs/mkdocs/requirements.txt @@ -1,11 +1,11 @@ -wheel==0.46.3 +wheel==0.47.0 mkdocs==1.6.1 # documentation framework -mkdocs-git-revision-date-localized-plugin==1.5.1 # plugin "git-revision-date-localized" -mkdocs-material==9.7.4 # theme for mkdocs +mkdocs-git-revision-date-localized-plugin==1.5.2 # plugin "git-revision-date-localized" +mkdocs-material==9.7.6 # theme for mkdocs mkdocs-material-extensions==1.3.1 # extensions mkdocs-minify-plugin==0.8.0 # plugin "minify" -mkdocs-redirects==1.2.2 # plugin "redirects" +mkdocs-redirects==1.2.3 # plugin "redirects" mkdocs-htmlproofer-plugin==1.5.0 # plugin "htmlproofer" PyYAML==6.0.3 # linter diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 2a814d1e3a..5a7cdb6241 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -388,14 +388,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) ConstructibleObjectType ret; const auto* inner_object = j.template get_ptr(); - using value_type = typename ConstructibleObjectType::value_type; - std::transform( - inner_object->begin(), inner_object->end(), - std::inserter(ret, ret.begin()), - [](typename BasicJsonType::object_t::value_type const & p) + for (const auto& p : *inner_object) { - return value_type(p.first, p.second.template get()); - }); + ret.emplace(p.first, p.second.template get()); + } obj = std::move(ret); } diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 93e3216b95..44448611a3 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -35,7 +35,7 @@ This class implements a both iterators (iterator and const_iterator) for the been set (e.g., by a constructor or a copy assignment). If the iterator is default-constructed, it is *uninitialized* and most methods are undefined. **The library uses assertions to detect calls on uninitialized iterators.** -@requirement The class satisfies the following concept requirements: +@requirement REQ-JSON-01 The class satisfies the following concept requirements: - [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): The iterator that can be moved can be moved in both directions (i.e. diff --git a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp index 59cec75b4e..b452cfcce0 100644 --- a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +++ b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -29,7 +29,7 @@ namespace detail iterator (to create @ref reverse_iterator) and @ref const_iterator (to create @ref const_reverse_iterator). -@requirement The class satisfies the following concept requirements: +@requirement REQ-JSON-02 The class satisfies the following concept requirements: - [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): The iterator that can be moved can be moved in both directions (i.e. diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index ac50a8703b..0767484f88 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -154,6 +154,44 @@ class json_pointer return res; } + /// @brief remove first reference token + /// @sa https://json.nlohmann.me/api/json_pointer/pop_front/ + void pop_front() + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); + } + + reference_tokens.erase(reference_tokens.begin()); + } + + /// @brief return first reference token + /// @sa https://json.nlohmann.me/api/json_pointer/front/ + const string_t& front() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); + } + + return reference_tokens.front(); + } + + /// @brief append an unescaped token at the start of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_front/ + void push_front(const string_t& token) + { + reference_tokens.insert(reference_tokens.begin(), token); + } + + /// @brief append an unescaped token at the start of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_front/ + void push_front(string_t&& token) + { + reference_tokens.insert(reference_tokens.begin(), std::move(token)); + } + /// @brief remove last reference token /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ void pop_back() diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index afb400c90b..791e692b89 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -253,6 +253,61 @@ e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } + + +/*! +@brief function to wrap JSON_THROW_MACRO - there can be compilation errors about + there being no arguments to JSON_THROW that depend on template arguments + if this is not used to call JSON_THROW +*/ +template +void templated_json_throw(ExceptionType exception) +{ + JSON_THROW(exception); + + /* JSON_THROW(exception) discards exception and aborts - void cast needed to supress + compilation error if compiled with -Werror and Wunused-parameter */ + (void)exception; +} + +/*! +@brief macro to briefly define a mapping between an enum and JSON with exception + on invalid input +@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT +@since version 3.12.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + if (it != std::end(m)) j = it->second; \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE, nullptr)); \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + if (it != std::end(m)) e = it->first; \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \ + } + // Ugly macros to avoid uglier copy-paste when specializing basic_json. They // may be removed in the future once the class is split. @@ -403,11 +458,113 @@ #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) +#define NLOHMANN_JSON_DOUBLE_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_DOUBLE_PASTE63, \ + NLOHMANN_JSON_DOUBLE_PASTE63, \ + NLOHMANN_JSON_DOUBLE_PASTE61, \ + NLOHMANN_JSON_DOUBLE_PASTE61, \ + NLOHMANN_JSON_DOUBLE_PASTE59, \ + NLOHMANN_JSON_DOUBLE_PASTE59, \ + NLOHMANN_JSON_DOUBLE_PASTE57, \ + NLOHMANN_JSON_DOUBLE_PASTE57, \ + NLOHMANN_JSON_DOUBLE_PASTE55, \ + NLOHMANN_JSON_DOUBLE_PASTE55, \ + NLOHMANN_JSON_DOUBLE_PASTE53, \ + NLOHMANN_JSON_DOUBLE_PASTE53, \ + NLOHMANN_JSON_DOUBLE_PASTE51, \ + NLOHMANN_JSON_DOUBLE_PASTE51, \ + NLOHMANN_JSON_DOUBLE_PASTE49, \ + NLOHMANN_JSON_DOUBLE_PASTE49, \ + NLOHMANN_JSON_DOUBLE_PASTE47, \ + NLOHMANN_JSON_DOUBLE_PASTE47, \ + NLOHMANN_JSON_DOUBLE_PASTE45, \ + NLOHMANN_JSON_DOUBLE_PASTE45, \ + NLOHMANN_JSON_DOUBLE_PASTE43, \ + NLOHMANN_JSON_DOUBLE_PASTE43, \ + NLOHMANN_JSON_DOUBLE_PASTE41, \ + NLOHMANN_JSON_DOUBLE_PASTE41, \ + NLOHMANN_JSON_DOUBLE_PASTE39, \ + NLOHMANN_JSON_DOUBLE_PASTE39, \ + NLOHMANN_JSON_DOUBLE_PASTE37, \ + NLOHMANN_JSON_DOUBLE_PASTE37, \ + NLOHMANN_JSON_DOUBLE_PASTE35, \ + NLOHMANN_JSON_DOUBLE_PASTE35, \ + NLOHMANN_JSON_DOUBLE_PASTE33, \ + NLOHMANN_JSON_DOUBLE_PASTE33, \ + NLOHMANN_JSON_DOUBLE_PASTE31, \ + NLOHMANN_JSON_DOUBLE_PASTE31, \ + NLOHMANN_JSON_DOUBLE_PASTE29, \ + NLOHMANN_JSON_DOUBLE_PASTE29, \ + NLOHMANN_JSON_DOUBLE_PASTE27, \ + NLOHMANN_JSON_DOUBLE_PASTE27, \ + NLOHMANN_JSON_DOUBLE_PASTE25, \ + NLOHMANN_JSON_DOUBLE_PASTE25, \ + NLOHMANN_JSON_DOUBLE_PASTE23, \ + NLOHMANN_JSON_DOUBLE_PASTE23, \ + NLOHMANN_JSON_DOUBLE_PASTE21, \ + NLOHMANN_JSON_DOUBLE_PASTE21, \ + NLOHMANN_JSON_DOUBLE_PASTE19, \ + NLOHMANN_JSON_DOUBLE_PASTE19, \ + NLOHMANN_JSON_DOUBLE_PASTE17, \ + NLOHMANN_JSON_DOUBLE_PASTE17, \ + NLOHMANN_JSON_DOUBLE_PASTE15, \ + NLOHMANN_JSON_DOUBLE_PASTE15, \ + NLOHMANN_JSON_DOUBLE_PASTE13, \ + NLOHMANN_JSON_DOUBLE_PASTE13, \ + NLOHMANN_JSON_DOUBLE_PASTE11, \ + NLOHMANN_JSON_DOUBLE_PASTE11, \ + NLOHMANN_JSON_DOUBLE_PASTE9, \ + NLOHMANN_JSON_DOUBLE_PASTE9, \ + NLOHMANN_JSON_DOUBLE_PASTE7, \ + NLOHMANN_JSON_DOUBLE_PASTE7, \ + NLOHMANN_JSON_DOUBLE_PASTE5, \ + NLOHMANN_JSON_DOUBLE_PASTE5, \ + NLOHMANN_JSON_DOUBLE_PASTE3, \ + NLOHMANN_JSON_DOUBLE_PASTE3, \ + NLOHMANN_JSON_DOUBLE_PASTE1, \ + NLOHMANN_JSON_DOUBLE_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) func(v1, v2) +#define NLOHMANN_JSON_DOUBLE_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE3(func, v3, v4) +#define NLOHMANN_JSON_DOUBLE_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE5(func, v3, v4, v5, v6) +#define NLOHMANN_JSON_DOUBLE_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE7(func, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_DOUBLE_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE9(func, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_DOUBLE_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE11(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_DOUBLE_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE13(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_DOUBLE_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE15(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_DOUBLE_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE17(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_DOUBLE_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE19(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_DOUBLE_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE21(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_DOUBLE_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE23(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_DOUBLE_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE25(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_DOUBLE_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE27(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_DOUBLE_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE29(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_DOUBLE_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE31(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_DOUBLE_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE33(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_DOUBLE_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE35(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_DOUBLE_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE37(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_DOUBLE_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE39(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_DOUBLE_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE41(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_DOUBLE_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE43(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_DOUBLE_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE45(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_DOUBLE_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE47(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_DOUBLE_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE49(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_DOUBLE_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE51(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_DOUBLE_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE53(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_DOUBLE_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE55(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_DOUBLE_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE57(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_DOUBLE_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE59(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_DOUBLE_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE61(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; +#define NLOHMANN_JSON_TO_WITH_NAME(v1, v2) nlohmann_json_j[v1] = nlohmann_json_t.v2; +#define NLOHMANN_JSON_FROM_WITH_NAME(v1, v2) nlohmann_json_j.at(v1).get_to(nlohmann_json_t.v2); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME(v1, v2) nlohmann_json_t.v2 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(v1, nlohmann_json_default_obj.v2) : nlohmann_json_default_obj.v2; + +#define NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(...) template::value, int> = 0> __VA_ARGS__ + /*! @brief macro @def NLOHMANN_DEFINE_TYPE_INTRUSIVE @@ -415,10 +572,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -427,10 +586,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -439,8 +600,10 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -449,10 +612,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -461,10 +626,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -473,8 +640,10 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -483,10 +652,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -495,10 +666,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -507,8 +680,11 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + /*! @brief macro @@ -517,10 +693,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -529,10 +707,12 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -541,8 +721,32 @@ @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE(Type) \ template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + friend void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType&, Type&) noexcept { } /* NOLINT(bugprone-macro-parentheses) */ + +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE(Type) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType&, Type&) noexcept { } /* NOLINT(bugprone-macro-parentheses) */ // inspired from https://stackoverflow.com/a/26745591 // allows calling any std function as if (e.g., with begin): @@ -599,3 +803,7 @@ #ifndef JSON_USE_GLOBAL_UDLS #define JSON_USE_GLOBAL_UDLS 1 #endif + +#ifndef JSON_BRACE_INIT_COPY_SEMANTICS + #define JSON_BRACE_INIT_COPY_SEMANTICS 0 +#endif diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp index af6d8370cb..8b9b04459d 100644 --- a/include/nlohmann/detail/macro_unscope.hpp +++ b/include/nlohmann/detail/macro_unscope.hpp @@ -26,6 +26,7 @@ #undef JSON_NO_UNIQUE_ADDRESS #undef JSON_DISABLE_ENUM_SERIALIZATION #undef JSON_USE_GLOBAL_UDLS +#undef JSON_BRACE_INIT_COPY_SEMANTICS #ifndef JSON_TEST_KEEP_MACROS #undef JSON_CATCH diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index aeec34eebb..25a64d6486 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -825,14 +825,27 @@ class serializer o->write_characters(begin, static_cast(end - begin)); } + JSON_HEDLEY_NON_NULL(1) + static int snprintf_float(char* buf, std::size_t size, int d, double x) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return (std::snprintf)(buf, size, "%.*g", d, x); + } + + JSON_HEDLEY_NON_NULL(1) + static int snprintf_float(char* buf, std::size_t size, int d, long double x) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return (std::snprintf)(buf, size, "%.*Lg", d, x); + } + void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) { // get the number of digits for a float -> text -> float round-trip static constexpr auto d = std::numeric_limits::max_digits10; // the actual conversion - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); + std::ptrdiff_t len = snprintf_float(number_buffer.data(), number_buffer.size(), d, x); // negative value indicates an error JSON_ASSERT(len > 0); diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 0b8f155ac5..47d5c51ff3 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -18,6 +18,16 @@ #ifndef INCLUDE_NLOHMANN_JSON_HPP_ #define INCLUDE_NLOHMANN_JSON_HPP_ +// Workaround for GCC template redefinition errors in C++ modules +// When nlohmann/json.hpp is included in a C++20 module preamble after +// other module imports, GCC may report spurious redefinition errors for +// STL templates. These pragmas suppress those false positives. +// See: https://github.com/nlohmann/json/issues/5103 +#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wignored-attributes" +#endif + #include // all_of, find, for_each #include // nullptr_t, ptrdiff_t, size_t #include // hash, less @@ -741,10 +751,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #endif } - iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) + iterator set_parents(iterator it, std::ptrdiff_t count_set_parents) { #if JSON_DIAGNOSTICS - for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) + for (std::ptrdiff_t i = 0; i < count_set_parents; ++i) { (it + i)->m_parent = this; } @@ -955,6 +965,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } else { +#if JSON_BRACE_INIT_COPY_SEMANTICS + if (type_deduction && init.size() == 1) + { + *this = init.begin()->moved_or_copied(); + set_parents(); + assert_invariant(); + return; + } +#endif // the initializer list describes an array -> create an array m_data.m_type = value_t::array; m_data.m_value.array = create(init.begin(), init.end()); @@ -4122,22 +4141,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool ignore_comments = false, const bool ignore_trailing_commas = false) { -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull-compare" -#endif - if (sax == nullptr) - { - JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr)); - } -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif auto ia = detail::input_adapter(std::forward(i)); return format == input_format_t::json ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict) @@ -4154,22 +4157,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool ignore_comments = false, const bool ignore_trailing_commas = false) { -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull-compare" -#endif - if (sax == nullptr) - { - JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr)); - } -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif auto ia = detail::input_adapter(std::move(first), std::move(last)); return format == input_format_t::json ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict) @@ -4190,22 +4177,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool ignore_comments = false, const bool ignore_trailing_commas = false) { -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull-compare" -#endif - if (sax == nullptr) - { - JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr)); - } -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif auto ia = i.get(); return format == input_format_t::json // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) @@ -5383,4 +5354,9 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC #include +// End of GCC diagnostic pragmas for C++ modules support +#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L + #pragma GCC diagnostic pop +#endif + #endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/include/nlohmann/ordered_map.hpp b/include/nlohmann/ordered_map.hpp index d8606f82fd..7b8cf70f4c 100644 --- a/include/nlohmann/ordered_map.hpp +++ b/include/nlohmann/ordered_map.hpp @@ -50,6 +50,25 @@ template , : Container{first, last, alloc} {} ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) : Container{init, alloc} {} + ordered_map(const ordered_map&) = default; + ordered_map(ordered_map&&) noexcept(std::is_nothrow_move_constructible::value) = default; + ~ordered_map() = default; + + ordered_map& operator=(const ordered_map& other) + { + if (this != &other) + { + ordered_map tmp(other); + Container::operator=(std::move(static_cast(tmp))); + } + return *this; + } + + ordered_map& operator=(ordered_map&& other) noexcept(std::is_nothrow_move_assignable::value) + { + Container::operator=(std::move(static_cast(other))); + return *this; + } std::pair emplace(const key_type& key, T&& t) { @@ -321,6 +340,20 @@ template , return Container::end(); } + template::value, int> = 0> + const_iterator find(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (m_compare(it->first, key)) + { + return it; + } + } + return Container::end(); + } + std::pair insert( value_type&& value ) { return emplace(value.first, std::move(value.second)); diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index e2bb8517b6..e68d2f2fd9 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -18,6 +18,16 @@ #ifndef INCLUDE_NLOHMANN_JSON_HPP_ #define INCLUDE_NLOHMANN_JSON_HPP_ +// Workaround for GCC template redefinition errors in C++ modules +// When nlohmann/json.hpp is included in a C++20 module preamble after +// other module imports, GCC may report spurious redefinition errors for +// STL templates. These pragmas suppress those false positives. +// See: https://github.com/nlohmann/json/issues/5103 +#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wignored-attributes" +#endif + #include // all_of, find, for_each #include // nullptr_t, ptrdiff_t, size_t #include // hash, less @@ -2617,6 +2627,61 @@ JSON_HEDLEY_DIAGNOSTIC_POP e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } + + +/*! +@brief function to wrap JSON_THROW_MACRO - there can be compilation errors about + there being no arguments to JSON_THROW that depend on template arguments + if this is not used to call JSON_THROW +*/ +template +void templated_json_throw(ExceptionType exception) +{ + JSON_THROW(exception); + + /* JSON_THROW(exception) discards exception and aborts - void cast needed to supress + compilation error if compiled with -Werror and Wunused-parameter */ + (void)exception; +} + +/*! +@brief macro to briefly define a mapping between an enum and JSON with exception + on invalid input +@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT +@since version 3.12.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + if (it != std::end(m)) j = it->second; \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE, nullptr)); \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + if (it != std::end(m)) e = it->first; \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \ + } + // Ugly macros to avoid uglier copy-paste when specializing basic_json. They // may be removed in the future once the class is split. @@ -2767,11 +2832,113 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) +#define NLOHMANN_JSON_DOUBLE_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_DOUBLE_PASTE63, \ + NLOHMANN_JSON_DOUBLE_PASTE63, \ + NLOHMANN_JSON_DOUBLE_PASTE61, \ + NLOHMANN_JSON_DOUBLE_PASTE61, \ + NLOHMANN_JSON_DOUBLE_PASTE59, \ + NLOHMANN_JSON_DOUBLE_PASTE59, \ + NLOHMANN_JSON_DOUBLE_PASTE57, \ + NLOHMANN_JSON_DOUBLE_PASTE57, \ + NLOHMANN_JSON_DOUBLE_PASTE55, \ + NLOHMANN_JSON_DOUBLE_PASTE55, \ + NLOHMANN_JSON_DOUBLE_PASTE53, \ + NLOHMANN_JSON_DOUBLE_PASTE53, \ + NLOHMANN_JSON_DOUBLE_PASTE51, \ + NLOHMANN_JSON_DOUBLE_PASTE51, \ + NLOHMANN_JSON_DOUBLE_PASTE49, \ + NLOHMANN_JSON_DOUBLE_PASTE49, \ + NLOHMANN_JSON_DOUBLE_PASTE47, \ + NLOHMANN_JSON_DOUBLE_PASTE47, \ + NLOHMANN_JSON_DOUBLE_PASTE45, \ + NLOHMANN_JSON_DOUBLE_PASTE45, \ + NLOHMANN_JSON_DOUBLE_PASTE43, \ + NLOHMANN_JSON_DOUBLE_PASTE43, \ + NLOHMANN_JSON_DOUBLE_PASTE41, \ + NLOHMANN_JSON_DOUBLE_PASTE41, \ + NLOHMANN_JSON_DOUBLE_PASTE39, \ + NLOHMANN_JSON_DOUBLE_PASTE39, \ + NLOHMANN_JSON_DOUBLE_PASTE37, \ + NLOHMANN_JSON_DOUBLE_PASTE37, \ + NLOHMANN_JSON_DOUBLE_PASTE35, \ + NLOHMANN_JSON_DOUBLE_PASTE35, \ + NLOHMANN_JSON_DOUBLE_PASTE33, \ + NLOHMANN_JSON_DOUBLE_PASTE33, \ + NLOHMANN_JSON_DOUBLE_PASTE31, \ + NLOHMANN_JSON_DOUBLE_PASTE31, \ + NLOHMANN_JSON_DOUBLE_PASTE29, \ + NLOHMANN_JSON_DOUBLE_PASTE29, \ + NLOHMANN_JSON_DOUBLE_PASTE27, \ + NLOHMANN_JSON_DOUBLE_PASTE27, \ + NLOHMANN_JSON_DOUBLE_PASTE25, \ + NLOHMANN_JSON_DOUBLE_PASTE25, \ + NLOHMANN_JSON_DOUBLE_PASTE23, \ + NLOHMANN_JSON_DOUBLE_PASTE23, \ + NLOHMANN_JSON_DOUBLE_PASTE21, \ + NLOHMANN_JSON_DOUBLE_PASTE21, \ + NLOHMANN_JSON_DOUBLE_PASTE19, \ + NLOHMANN_JSON_DOUBLE_PASTE19, \ + NLOHMANN_JSON_DOUBLE_PASTE17, \ + NLOHMANN_JSON_DOUBLE_PASTE17, \ + NLOHMANN_JSON_DOUBLE_PASTE15, \ + NLOHMANN_JSON_DOUBLE_PASTE15, \ + NLOHMANN_JSON_DOUBLE_PASTE13, \ + NLOHMANN_JSON_DOUBLE_PASTE13, \ + NLOHMANN_JSON_DOUBLE_PASTE11, \ + NLOHMANN_JSON_DOUBLE_PASTE11, \ + NLOHMANN_JSON_DOUBLE_PASTE9, \ + NLOHMANN_JSON_DOUBLE_PASTE9, \ + NLOHMANN_JSON_DOUBLE_PASTE7, \ + NLOHMANN_JSON_DOUBLE_PASTE7, \ + NLOHMANN_JSON_DOUBLE_PASTE5, \ + NLOHMANN_JSON_DOUBLE_PASTE5, \ + NLOHMANN_JSON_DOUBLE_PASTE3, \ + NLOHMANN_JSON_DOUBLE_PASTE3, \ + NLOHMANN_JSON_DOUBLE_PASTE1, \ + NLOHMANN_JSON_DOUBLE_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) func(v1, v2) +#define NLOHMANN_JSON_DOUBLE_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE3(func, v3, v4) +#define NLOHMANN_JSON_DOUBLE_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE5(func, v3, v4, v5, v6) +#define NLOHMANN_JSON_DOUBLE_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE7(func, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_DOUBLE_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE9(func, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_DOUBLE_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE11(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_DOUBLE_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE13(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_DOUBLE_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE15(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_DOUBLE_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE17(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_DOUBLE_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE19(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_DOUBLE_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE21(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_DOUBLE_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE23(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_DOUBLE_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE25(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_DOUBLE_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE27(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_DOUBLE_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE29(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_DOUBLE_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE31(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_DOUBLE_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE33(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_DOUBLE_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE35(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_DOUBLE_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE37(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_DOUBLE_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE39(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_DOUBLE_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE41(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_DOUBLE_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE43(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_DOUBLE_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE45(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_DOUBLE_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE47(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_DOUBLE_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE49(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_DOUBLE_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE51(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_DOUBLE_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE53(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_DOUBLE_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE55(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_DOUBLE_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE57(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_DOUBLE_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE59(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_DOUBLE_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE61(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; +#define NLOHMANN_JSON_TO_WITH_NAME(v1, v2) nlohmann_json_j[v1] = nlohmann_json_t.v2; +#define NLOHMANN_JSON_FROM_WITH_NAME(v1, v2) nlohmann_json_j.at(v1).get_to(nlohmann_json_t.v2); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME(v1, v2) nlohmann_json_t.v2 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(v1, nlohmann_json_default_obj.v2) : nlohmann_json_default_obj.v2; + +#define NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(...) template::value, int> = 0> __VA_ARGS__ + /*! @brief macro @def NLOHMANN_DEFINE_TYPE_INTRUSIVE @@ -2779,10 +2946,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2791,10 +2960,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2803,8 +2974,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2813,10 +2986,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2825,10 +3000,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2837,8 +3014,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ */ #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2847,10 +3026,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2859,10 +3040,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2871,8 +3054,11 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + /*! @brief macro @@ -2881,10 +3067,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2893,10 +3081,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) /*! @brief macro @@ -2905,8 +3095,32 @@ JSON_HEDLEY_DIAGNOSTIC_POP @sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ */ #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE(Type) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + friend void from_json(const BasicJsonType&, Type&) noexcept { } /* NOLINT(bugprone-macro-parentheses) */ + +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE(Type) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType&, Type&) noexcept { } /* NOLINT(bugprone-macro-parentheses) */ // inspired from https://stackoverflow.com/a/26745591 // allows calling any std function as if (e.g., with begin): @@ -2964,6 +3178,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_USE_GLOBAL_UDLS 1 #endif +#ifndef JSON_BRACE_INIT_COPY_SEMANTICS + #define JSON_BRACE_INIT_COPY_SEMANTICS 0 +#endif + #if JSON_HAS_THREE_WAY_COMPARISON #include // partial_ordering #endif @@ -5302,14 +5520,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) ConstructibleObjectType ret; const auto* inner_object = j.template get_ptr(); - using value_type = typename ConstructibleObjectType::value_type; - std::transform( - inner_object->begin(), inner_object->end(), - std::inserter(ret, ret.begin()), - [](typename BasicJsonType::object_t::value_type const & p) + for (const auto& p : *inner_object) { - return value_type(p.first, p.second.template get()); - }); + ret.emplace(p.first, p.second.template get()); + } obj = std::move(ret); } @@ -13803,7 +14017,7 @@ This class implements a both iterators (iterator and const_iterator) for the been set (e.g., by a constructor or a copy assignment). If the iterator is default-constructed, it is *uninitialized* and most methods are undefined. **The library uses assertions to detect calls on uninitialized iterators.** -@requirement The class satisfies the following concept requirements: +@requirement REQ-JSON-01 The class satisfies the following concept requirements: - [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): The iterator that can be moved can be moved in both directions (i.e. @@ -14562,7 +14776,7 @@ namespace detail iterator (to create @ref reverse_iterator) and @ref const_iterator (to create @ref const_reverse_iterator). -@requirement The class satisfies the following concept requirements: +@requirement REQ-JSON-02 The class satisfies the following concept requirements: - [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): The iterator that can be moved can be moved in both directions (i.e. @@ -14868,6 +15082,44 @@ class json_pointer return res; } + /// @brief remove first reference token + /// @sa https://json.nlohmann.me/api/json_pointer/pop_front/ + void pop_front() + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); + } + + reference_tokens.erase(reference_tokens.begin()); + } + + /// @brief return first reference token + /// @sa https://json.nlohmann.me/api/json_pointer/front/ + const string_t& front() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); + } + + return reference_tokens.front(); + } + + /// @brief append an unescaped token at the start of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_front/ + void push_front(const string_t& token) + { + reference_tokens.insert(reference_tokens.begin(), token); + } + + /// @brief append an unescaped token at the start of the reference pointer + /// @sa https://json.nlohmann.me/api/json_pointer/push_front/ + void push_front(string_t&& token) + { + reference_tokens.insert(reference_tokens.begin(), std::move(token)); + } + /// @brief remove last reference token /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ void pop_back() @@ -19769,14 +20021,27 @@ class serializer o->write_characters(begin, static_cast(end - begin)); } + JSON_HEDLEY_NON_NULL(1) + static int snprintf_float(char* buf, std::size_t size, int d, double x) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return (std::snprintf)(buf, size, "%.*g", d, x); + } + + JSON_HEDLEY_NON_NULL(1) + static int snprintf_float(char* buf, std::size_t size, int d, long double x) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return (std::snprintf)(buf, size, "%.*Lg", d, x); + } + void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) { // get the number of digits for a float -> text -> float round-trip static constexpr auto d = std::numeric_limits::max_digits10; // the actual conversion - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); + std::ptrdiff_t len = snprintf_float(number_buffer.data(), number_buffer.size(), d, x); // negative value indicates an error JSON_ASSERT(len > 0); @@ -19990,6 +20255,25 @@ template , : Container{first, last, alloc} {} ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) : Container{init, alloc} {} + ordered_map(const ordered_map&) = default; + ordered_map(ordered_map&&) noexcept(std::is_nothrow_move_constructible::value) = default; + ~ordered_map() = default; + + ordered_map& operator=(const ordered_map& other) + { + if (this != &other) + { + ordered_map tmp(other); + Container::operator=(std::move(static_cast(tmp))); + } + return *this; + } + + ordered_map& operator=(ordered_map&& other) noexcept(std::is_nothrow_move_assignable::value) + { + Container::operator=(std::move(static_cast(other))); + return *this; + } std::pair emplace(const key_type& key, T&& t) { @@ -20261,6 +20545,20 @@ template , return Container::end(); } + template::value, int> = 0> + const_iterator find(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (m_compare(it->first, key)) + { + return it; + } + } + return Container::end(); + } + std::pair insert( value_type&& value ) { return emplace(value.first, std::move(value.second)); @@ -20978,10 +21276,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #endif } - iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) + iterator set_parents(iterator it, std::ptrdiff_t count_set_parents) { #if JSON_DIAGNOSTICS - for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) + for (std::ptrdiff_t i = 0; i < count_set_parents; ++i) { (it + i)->m_parent = this; } @@ -21192,6 +21490,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } else { +#if JSON_BRACE_INIT_COPY_SEMANTICS + if (type_deduction && init.size() == 1) + { + *this = init.begin()->moved_or_copied(); + set_parents(); + assert_invariant(); + return; + } +#endif // the initializer list describes an array -> create an array m_data.m_type = value_t::array; m_data.m_value.array = create(init.begin(), init.end()); @@ -24359,22 +24666,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool ignore_comments = false, const bool ignore_trailing_commas = false) { -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull-compare" -#endif - if (sax == nullptr) - { - JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr)); - } -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif auto ia = detail::input_adapter(std::forward(i)); return format == input_format_t::json ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict) @@ -24391,22 +24682,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool ignore_comments = false, const bool ignore_trailing_commas = false) { -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull-compare" -#endif - if (sax == nullptr) - { - JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr)); - } -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif auto ia = detail::input_adapter(std::move(first), std::move(last)); return format == input_format_t::json ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict) @@ -24427,22 +24702,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool ignore_comments = false, const bool ignore_trailing_commas = false) { -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnonnull-compare" -#endif - if (sax == nullptr) - { - JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr)); - } -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif auto ia = i.get(); return format == input_format_t::json // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) @@ -25647,6 +25906,7 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC #undef JSON_NO_UNIQUE_ADDRESS #undef JSON_DISABLE_ENUM_SERIALIZATION #undef JSON_USE_GLOBAL_UDLS +#undef JSON_BRACE_INIT_COPY_SEMANTICS #ifndef JSON_TEST_KEEP_MACROS #undef JSON_CATCH @@ -25827,4 +26087,9 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC +// End of GCC diagnostic pragmas for C++ modules support +#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L + #pragma GCC diagnostic pop +#endif + #endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/src/modules/json.cppm b/src/modules/json.cppm index 623d8cb81f..15207535fe 100644 --- a/src/modules/json.cppm +++ b/src/modules/json.cppm @@ -1,32 +1,52 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + module; +// GCC workaround for C++ modules support. +// When using C++20 modules, some compilers (particularly GCC) may have issues +// with template instantiations in the module preamble. If you encounter +// "redefinition" errors when including nlohmann/json.hpp, try one of: +// 1. Include nlohmann/json.hpp in your module preamble BEFORE other #includes +// 2. Or use: import nlohmann.json; instead of #include +// 3. Or upgrade to a newer GCC version with better modules support. +// See: https://github.com/nlohmann/json/issues/5103 + #include export module nlohmann.json; -export namespace nlohmann { - using ::nlohmann::adl_serializer; - using ::nlohmann::basic_json; - using ::nlohmann::json; - using ::nlohmann::json_pointer; - using ::nlohmann::ordered_json; - using ::nlohmann::ordered_map; -} // namespace nlohmann - +export NLOHMANN_JSON_NAMESPACE_BEGIN +using NLOHMANN_JSON_NAMESPACE::adl_serializer; +using NLOHMANN_JSON_NAMESPACE::basic_json; +using NLOHMANN_JSON_NAMESPACE::json; +using NLOHMANN_JSON_NAMESPACE::json_pointer; +using NLOHMANN_JSON_NAMESPACE::ordered_json; +using NLOHMANN_JSON_NAMESPACE::ordered_map; +using NLOHMANN_JSON_NAMESPACE::to_string; + +inline namespace literals +{ +inline namespace json_literals +{ + using NLOHMANN_JSON_NAMESPACE::literals::json_literals::operator""_json; + using NLOHMANN_JSON_NAMESPACE::literals::json_literals::operator""_json_pointer; +} // namespace json_literals +} // namespace literals + +// Note: the following nlohmann::detail symbols must be exported due to +// an MSVC bug failing to compile without these symbols visible (ticket #3970) namespace detail { - export using NLOHMANN_JSON_NAMESPACE::detail::json_sax_dom_callback_parser; - export using NLOHMANN_JSON_NAMESPACE::detail::unknown_size; + using NLOHMANN_JSON_NAMESPACE::detail::json_sax_dom_callback_parser; + using NLOHMANN_JSON_NAMESPACE::detail::unknown_size; } // namespace detail -export using NLOHMANN_JSON_NAMESPACE::adl_serializer; -export using NLOHMANN_JSON_NAMESPACE::basic_json; -export using NLOHMANN_JSON_NAMESPACE::json; -export using NLOHMANN_JSON_NAMESPACE::json_pointer; -export using NLOHMANN_JSON_NAMESPACE::ordered_json; -export using NLOHMANN_JSON_NAMESPACE::ordered_map; -export using NLOHMANN_JSON_NAMESPACE::to_string; - NLOHMANN_JSON_NAMESPACE_END diff --git a/tests/src/unit-class_parser.cpp b/tests/src/unit-class_parser.cpp index 9c5fadc295..4ce7c43465 100644 --- a/tests/src/unit-class_parser.cpp +++ b/tests/src/unit-class_parser.cpp @@ -1644,33 +1644,6 @@ TEST_CASE("parser class") SECTION("SAX parser") { - SECTION("null sax handler") - { -# if defined(__has_feature) -#if !__has_feature(undefined_behavior_sanitizer) - const std::string s = "some_string"; - SaxCountdown* p = nullptr; - CHECK_THROWS_WITH_AS(json::sax_parse(s, p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker) - CHECK_THROWS_WITH_AS(json::sax_parse(s.begin(), s.end(), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker) - CHECK_THROWS_WITH_AS(json::sax_parse(nlohmann::detail::span_input_adapter(s.c_str(), s.size()), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker) -#endif -#else - const std::string s = "some_string"; - SaxCountdown* p = nullptr; - CHECK_THROWS_WITH_AS(json::sax_parse(s, p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker) - CHECK_THROWS_WITH_AS(json::sax_parse(s.begin(), s.end(), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker) - CHECK_THROWS_WITH_AS(json::sax_parse(nlohmann::detail::span_input_adapter(s.c_str(), s.size()), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker) -#endif - } - - SECTION("valid sax handler") - { - const std::string str = "some_string"; - SaxCountdown s(1); - CHECK(json::sax_parse(str, &s) == false); - CHECK(json::sax_parse(nlohmann::detail::span_input_adapter(str.c_str(), str.size()), &s) == false); - } - SECTION("} without value") { SaxCountdown s(1); diff --git a/tests/src/unit-conversions.cpp b/tests/src/unit-conversions.cpp index 81b8608fb8..7542ef630b 100644 --- a/tests/src/unit-conversions.cpp +++ b/tests/src/unit-conversions.cpp @@ -1657,6 +1657,84 @@ TEST_CASE("JSON to enum mapping") } } +enum class strict_cards {kreuz, pik, herz, karo, andere}; // andere not included in mapping + +// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(strict_cards, +{ + {strict_cards::kreuz, "kreuz"}, + {strict_cards::pik, "pik"}, + {strict_cards::pik, "puk"}, // second entry for cards::pik; will not be used + {strict_cards::herz, "herz"}, + {strict_cards::karo, "karo"} +}) + +enum StrictTaskState // NOLINT(cert-int09-c,readability-enum-initial-value,cppcoreguidelines-use-enum-class) +{ + STRICT_TS_STOPPED, + STRICT_TS_RUNNING, + STRICT_TS_COMPLETED, + STRICT_TS_OTHER, // STRICT_TS_OTHER not in mapping + STRICT_TS_INVALID = -1, +}; + +// NOLINTNEXTLINE(misc-const-correctness,misc-use-internal-linkage,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive +NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(StrictTaskState, +{ + {STRICT_TS_INVALID, nullptr}, + {STRICT_TS_STOPPED, "stopped"}, + {STRICT_TS_RUNNING, "running"}, + {STRICT_TS_COMPLETED, "completed"}, +}) + +TEST_CASE("Strict JSON to enum mapping") +{ + SECTION("enum class") + { + // enum -> json + CHECK(json(strict_cards::kreuz) == "kreuz"); + CHECK(json(strict_cards::pik) == "pik"); + CHECK(json(strict_cards::herz) == "herz"); + CHECK(json(strict_cards::karo) == "karo"); + + // json -> enum + CHECK(strict_cards::kreuz == json("kreuz")); + CHECK(strict_cards::pik == json("pik")); + CHECK(strict_cards::herz == json("herz")); + CHECK(strict_cards::karo == json("karo")); + + // invalid json -> exception thrown + json _; + CHECK_THROWS_WITH_AS(_ = json("what?").get(), "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"what?\"", json::out_of_range&); + + // conversion of unmapped enum -> exception thrown + CHECK_THROWS_WITH_AS(json(strict_cards::andere), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&); + } + + SECTION("traditional enum") + { + // enum -> json + CHECK(json(STRICT_TS_STOPPED) == "stopped"); + CHECK(json(STRICT_TS_RUNNING) == "running"); + CHECK(json(STRICT_TS_COMPLETED) == "completed"); + CHECK(json(STRICT_TS_INVALID) == json()); + + // json -> enum + CHECK(STRICT_TS_STOPPED == json("stopped")); + CHECK(STRICT_TS_RUNNING == json("running")); + CHECK(STRICT_TS_COMPLETED == json("completed")); + CHECK(STRICT_TS_INVALID == json()); + + // invalid json -> exception thrown + json _; + CHECK_THROWS_WITH_AS(_ = json("what?").get(), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState: \"what?\"", json::out_of_range&); + + // conversion of unmapped enum -> exception thrown + CHECK_THROWS_WITH_AS(json(STRICT_TS_OTHER), "[json.exception.out_of_range.410] enum value out of range for StrictTaskState", json::out_of_range&); + } +} + + #ifdef JSON_HAS_CPP_17 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM TEST_CASE("std::filesystem::path") @@ -1683,7 +1761,7 @@ TEST_CASE("std::filesystem::path") } #endif -#ifndef JSON_USE_IMPLICIT_CONVERSIONS +#if !JSON_USE_IMPLICIT_CONVERSIONS TEST_CASE("std::optional") { SECTION("null") diff --git a/tests/src/unit-json_pointer.cpp b/tests/src/unit-json_pointer.cpp index e1522c9f73..a8ed4a89e3 100644 --- a/tests/src/unit-json_pointer.cpp +++ b/tests/src/unit-json_pointer.cpp @@ -564,6 +564,14 @@ TEST_CASE("JSON pointers") CHECK(!ptr.empty()); CHECK(j[ptr] == j["answer"]["everything"]); + ptr.pop_front(); + CHECK(ptr.front() == "everything"); + ptr.pop_front(); + CHECK(ptr.empty()); + ptr.push_front("everything"); + ptr.push_front(answer); + CHECK(j[ptr] == j["answer"]["everything"]); + // check access via const pointer const auto cptr = ptr; CHECK(cptr.back() == "everything"); @@ -588,8 +596,17 @@ TEST_CASE("JSON pointers") CHECK(ptr.empty()); CHECK(j[ptr] == j); - CHECK_THROWS_WITH(ptr.pop_back(), - "[json.exception.out_of_range.405] JSON pointer has no parent"); + CHECK_THROWS_WITH_AS(ptr.pop_back(), + "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&); + + CHECK_THROWS_WITH_AS(ptr.back(), + "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&); + + CHECK_THROWS_WITH_AS(ptr.pop_front(), + "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&); + + CHECK_THROWS_WITH_AS(ptr.front(), + "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&); } SECTION("operators") diff --git a/tests/src/unit-ordered_json.cpp b/tests/src/unit-ordered_json.cpp index 10bb037bc8..a38a1a2b8f 100644 --- a/tests/src/unit-ordered_json.cpp +++ b/tests/src/unit-ordered_json.cpp @@ -69,3 +69,15 @@ TEST_CASE("ordered_json") CHECK(oj1.size() == 4); CHECK(oj1.dump() == "{\"c\":1,\"b\":2,\"a\":3,\"d\":42}"); } + +TEST_CASE("regression test for issue #3732 - iteration_proxy_value>") +{ + // Naming the proxy type in a function-parameter position forces eager + // instantiation of basic_json; previously this hit an + // incomplete-type error in set_parents(). + auto fn = [](nlohmann::detail::iteration_proxy_value> const & val) + { + return val.value(); + }; + static_cast(fn); +} diff --git a/tests/src/unit-ordered_map.cpp b/tests/src/unit-ordered_map.cpp index 76ed4f34f3..f380a98690 100644 --- a/tests/src/unit-ordered_map.cpp +++ b/tests/src/unit-ordered_map.cpp @@ -269,6 +269,11 @@ TEST_CASE("ordered_map") CHECK(com.find("vier") == com.end()); CHECK(com.find(std::string("vier")) == com.end()); CHECK(com.find(vier) == com.end()); + +#ifdef JSON_HAS_CPP_17 + CHECK(om.find(std::string_view("eins")) == om.begin()); + CHECK(com.find(std::string_view("eins")) == com.begin()); +#endif } SECTION("insert") diff --git a/tests/src/unit-regression2.cpp b/tests/src/unit-regression2.cpp index 39dd52378b..f60b4a277c 100644 --- a/tests/src/unit-regression2.cpp +++ b/tests/src/unit-regression2.cpp @@ -1203,4 +1203,130 @@ TEST_CASE_TEMPLATE("issue #4798 - nlohmann::json::to_msgpack() encode float NaN CHECK(json::from_cbor(cbor_z_3).get() == -std::numeric_limits::infinity()); } +TEST_CASE("regression test #5074 - portable workaround for single-element brace init") +{ + json const j_obj = {{"key", "value"}}; + + json const j = json::array({j_obj}); + CHECK(j.is_array()); + CHECK(j.size() == 1); + CHECK(j[0] == j_obj); +} + +#if defined(JSON_BRACE_INIT_COPY_SEMANTICS) && (JSON_BRACE_INIT_COPY_SEMANTICS == 1) +TEST_CASE("regression test #5074 - single-element brace init with JSON_BRACE_INIT_COPY_SEMANTICS") +{ + // with JSON_BRACE_INIT_COPY_SEMANTICS: single-element brace init copies/moves + json const j_obj = {{"key", "value"}, {"num", 42}}; + json const j_arr = {1, 2, 3}; + + // object: brace init copies instead of wrapping + json const j1{j_obj}; + CHECK(j1.is_object()); + CHECK(j1 == j_obj); + + // array: brace init copies instead of wrapping + json const j2{j_arr}; + CHECK(j2.is_array()); + CHECK(j2.size() == 3); + CHECK(j2 == j_arr); + + // primitives still work as initializer lists + json const j3{true}; + CHECK(j3.is_boolean()); + + json const j4{42}; + CHECK(j4.is_number_integer()); +} +#endif + +struct Example_5122 +{ + float b = 2; + nlohmann::ordered_map c{}; // NOLINT(readability-redundant-member-init): needed for GCC -Weffc++ + int a = 1; + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Example_5122, b, c, a) +}; + +TEST_CASE("regression test #5122 - from_json into types holding nlohmann::ordered_map") +{ + Example_5122 src; + src.c.emplace("first", "1"); + src.c.emplace("second", "2"); + + ordered_json const j = src; + Example_5122 const dst = j.get(); + + CHECK(dst.b == src.b); + CHECK(dst.a == src.a); + REQUIRE(dst.c.size() == src.c.size()); + auto src_it = src.c.begin(); + auto dst_it = dst.c.begin(); + for (; src_it != src.c.end(); ++src_it, ++dst_it) + { + CHECK(dst_it->first == src_it->first); + CHECK(dst_it->second == src_it->second); + } +} + +// -Wself-assign-overloaded was introduced in Clang 7. Gate the pragma on +// __has_warning so older Clang versions do not error with "unknown warning +// group". The __has_warning check has to stay inside the __clang__ branch +// because GCC does not provide it and would tokenize-error on the argument. +#if defined(__clang__) && defined(__has_warning) + #if __has_warning("-Wself-assign-overloaded") + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH + DOCTEST_CLANG_SUPPRESS_WARNING("-Wself-assign-overloaded") + #endif +#endif + +TEST_CASE("regression test #5122 - nlohmann::ordered_map copy-assignment is self-assignment safe") +{ + nlohmann::ordered_map m; + m.emplace("first", "1"); + m.emplace("second", "2"); + + // Insertion order is preserved by ordered_map, so we can check it directly. + m = m; + + REQUIRE(m.size() == 2); + auto it = m.begin(); + CHECK(it->first == "first"); + CHECK(it->second == "1"); + ++it; + CHECK(it->first == "second"); + CHECK(it->second == "2"); +} + +#if defined(__clang__) && defined(__has_warning) + #if __has_warning("-Wself-assign-overloaded") + DOCTEST_CLANG_SUPPRESS_WARNING_POP + #endif +#endif + +TEST_CASE("regression test #5122 - nlohmann::ordered_map move-assignment transfers contents") +{ + nlohmann::ordered_map src; + src.emplace("first", "1"); + src.emplace("second", "2"); + + nlohmann::ordered_map dst; + dst.emplace("stale", "x"); + dst = std::move(src); + + REQUIRE(dst.size() == 2); + auto it = dst.begin(); + CHECK(it->first == "first"); + CHECK(it->second == "1"); + ++it; + CHECK(it->first == "second"); + CHECK(it->second == "2"); + + // Re-assigning into the moved-from object must leave it in a usable state. + src = nlohmann::ordered_map {}; + src.emplace("after-move", "3"); + REQUIRE(src.size() == 1); + CHECK(src.begin()->first == "after-move"); +} + DOCTEST_CLANG_SUPPRESS_WARNING_POP diff --git a/tests/src/unit-serialization.cpp b/tests/src/unit-serialization.cpp index 5c2ab81482..f55ed84704 100644 --- a/tests/src/unit-serialization.cpp +++ b/tests/src/unit-serialization.cpp @@ -11,6 +11,7 @@ #include using nlohmann::json; +#include #include #include @@ -295,3 +296,89 @@ TEST_CASE("dump with binary values") "]"); } } + +TEST_CASE("dump for basic_json with long double number_float_t") +{ + // Custom basic_json instantiation with long double as NumberFloatType. + // On platforms where long double is wider than double (e.g. GCC/Clang on + // Linux/macOS x86_64), dump() goes through the snprintf path in + // serializer::dump_float(x, std::false_type). That branch must use the + // "%.*Lg" format specifier; using "%.*g" with a long double argument is + // undefined behavior and corrupts the output. + using long_double_json = nlohmann::basic_json; + + SECTION("round-trip dump/parse") + { + constexpr std::array values = + { + { + 0.0L, -0.0L, 1.0L, -1.0L, + 0.5L, -0.5L, 1.5L, -2.25L, + 1.23e45L, 1.23e-45L, + (std::numeric_limits::min)(), + std::numeric_limits::lowest(), + (std::numeric_limits::max)() + } + }; + + for (long double v : values) + { + const long_double_json j = v; + const auto s = j.dump(); + const auto j2 = long_double_json::parse(s); + CHECK(j2.template get() == v); + } + } + + SECTION("exact dump string for simple values") + { + CHECK(long_double_json(0.5L).dump() == "0.5"); + CHECK(long_double_json(-0.5L).dump() == "-0.5"); + CHECK(long_double_json(1.5L).dump() == "1.5"); + CHECK(long_double_json(-2.25L).dump() == "-2.25"); + CHECK(long_double_json(0.0L).dump() == "0.0"); + CHECK(long_double_json(1.0L).dump() == "1.0"); + CHECK(long_double_json(-1.0L).dump() == "-1.0"); + CHECK(long_double_json(100.0L).dump() == "100.0"); + } + + SECTION("NaN and infinity dump as null") + { + CHECK(long_double_json(std::numeric_limits::quiet_NaN()).dump() == "null"); + + // Probe the platform's runtime behavior — `volatile` forces a runtime + // call rather than constexpr-folding to a known answer at compile time. + // Skip the infinity assertions if std::isfinite() doesn't actually + // recognize long double infinity on this platform (notably, Valgrind + // 3.22's x87 80-bit emulation reports +/-inf as a large finite value). + // TODO(rusloker): remove this guard once Valgrind's 80-bit long double + // support ships (Valgrind bug https://bugs.kde.org/show_bug.cgi?id=197915, + // ASSIGNED since 2009 — the Valgrind project tracks its bugs on + // bugs.kde.org) and the minimum supported Valgrind version contains it. + const volatile long double inf_probe = std::numeric_limits::infinity(); + if (!std::isfinite(inf_probe)) + { + CHECK(long_double_json(std::numeric_limits::infinity()).dump() == "null"); + CHECK(long_double_json(-std::numeric_limits::infinity()).dump() == "null"); + } + } + + SECTION("dump output matches double for exactly-representable values") + { + auto check_same = [](long double v_ld, double v_d) + { + const long_double_json j_ld = v_ld; + const json j_d = v_d; + CHECK(j_ld.dump() == j_d.dump()); + }; + + check_same(0.0L, 0.0); + check_same(0.5L, 0.5); + check_same(-0.5L, -0.5); + check_same(1.5L, 1.5); + check_same(-2.25L, -2.25); + check_same(1.0L, 1.0); + check_same(100.0L, 100.0); + } +} diff --git a/tests/src/unit-udt_macro.cpp b/tests/src/unit-udt_macro.cpp index cd65134297..0ca906e390 100644 --- a/tests/src/unit-udt_macro.cpp +++ b/tests/src/unit-udt_macro.cpp @@ -94,6 +94,85 @@ class person_with_private_data_2 NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(person_with_private_data_2, age, name, metadata) }; +class person_with_private_data_3 +{ + private: + std::string name{}; // NOLINT(readability-redundant-member-init) + int age = 0; + json metadata = nullptr; + + public: + bool operator==(const person_with_private_data_3& rhs) const + { + return name == rhs.name && age == rhs.age && metadata == rhs.metadata; + } + + person_with_private_data_3() = default; + person_with_private_data_3(std::string name_, int age_, json metadata_) + : name(std::move(name_)) + , age(age_) + , metadata(std::move(metadata_)) + {} + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(person_with_private_data_3, "json_age", age, "json_name", name, "json_metadata", metadata) +}; + +class derived_person_with_private_data_3 : public person_with_private_data_3 +{ + private: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_with_private_data_3& rhs) const + { + return person_with_private_data_3::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_with_private_data_3() = default; + derived_person_with_private_data_3(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_with_private_data_3(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES(derived_person_with_private_data_3, person_with_private_data_3, "json_hair_color", hair_color) +}; + +class person_with_private_data_4 +{ + private: + std::string name{}; // NOLINT(readability-redundant-member-init) + int age = 0; + json metadata = nullptr; + + public: + bool operator==(const person_with_private_data_4& rhs) const + { + return name == rhs.name && age == rhs.age && metadata == rhs.metadata; + } + + person_with_private_data_4() = default; + person_with_private_data_4(std::string name_, int age_, json metadata_) + : name(std::move(name_)) + , age(age_) + , metadata(std::move(metadata_)) + {} + + std::string getName() const + { + return name; + } + int getAge() const + { + return age; + } + json getMetadata() const + { + return metadata; + } + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(person_with_private_data_4, "json_age", age, "json_name", name, "json_metadata", metadata) +}; + class derived_person_with_private_data_2 : public person_with_private_data_2 { private: @@ -119,6 +198,31 @@ class derived_person_with_private_data_2 : public person_with_private_data_2 NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(derived_person_with_private_data_2, person_with_private_data_2, hair_color) }; +class derived_person_with_private_data_4 : public person_with_private_data_4 +{ + private: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_with_private_data_4& rhs) const + { + return person_with_private_data_4::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_with_private_data_4() = default; + derived_person_with_private_data_4(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_with_private_data_4(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + std::string getHairColor() const + { + return hair_color; + } + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(derived_person_with_private_data_4, person_with_private_data_4, "json_hair_color", hair_color) +}; + class person_without_private_data_1 { public: @@ -267,6 +371,154 @@ class derived_person_without_private_data_3 : public person_without_private_data // NOLINTNEXTLINE(misc-use-internal-linkage) NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(derived_person_without_private_data_3, person_without_private_data_3, hair_color) +class person_without_private_data_4 +{ + public: + std::string name{}; // NOLINT(readability-redundant-member-init) + int age = 0; + json metadata = nullptr; + + bool operator==(const person_without_private_data_4& rhs) const + { + return name == rhs.name && age == rhs.age && metadata == rhs.metadata; + } + + person_without_private_data_4() = default; + person_without_private_data_4(std::string name_, int age_, json metadata_) + : name(std::move(name_)) + , age(age_) + , metadata(std::move(metadata_)) + {} + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(person_without_private_data_4, "json_age", age, "json_name", name, "json_metadata", metadata) +}; + +class derived_person_without_private_data_4 : public person_without_private_data_4 +{ + public: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_without_private_data_4& rhs) const + { + return person_without_private_data_4::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_without_private_data_4() = default; + derived_person_without_private_data_4(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_without_private_data_4(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES(derived_person_without_private_data_4, person_without_private_data_4, "json_hair_color", hair_color) +}; + +class person_without_private_data_5 +{ + public: + std::string name{}; // NOLINT(readability-redundant-member-init) + int age = 0; + json metadata = nullptr; + + bool operator==(const person_without_private_data_5& rhs) const + { + return name == rhs.name && age == rhs.age && metadata == rhs.metadata; + } + + person_without_private_data_5() = default; + person_without_private_data_5(std::string name_, int age_, json metadata_) + : name(std::move(name_)) + , age(age_) + , metadata(std::move(metadata_)) + {} +}; + +// NOLINTNEXTLINE(misc-use-internal-linkage) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES(person_without_private_data_5, "json_age", age, "json_name", name, "json_metadata", metadata) + +class derived_person_without_private_data_5 : public person_without_private_data_5 +{ + public: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_without_private_data_5& rhs) const + { + return person_without_private_data_5::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_without_private_data_5() = default; + derived_person_without_private_data_5(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_without_private_data_5(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} +}; + +// NOLINTNEXTLINE(misc-use-internal-linkage) +NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES(derived_person_without_private_data_5, person_without_private_data_5, "json_hair_color", hair_color) + +class person_without_private_data_6 +{ + public: + std::string name{}; // NOLINT(readability-redundant-member-init) + int age = 0; + json metadata = nullptr; + + bool operator==(const person_without_private_data_6& rhs) const + { + return name == rhs.name && age == rhs.age && metadata == rhs.metadata; + } + + person_without_private_data_6() = default; + person_without_private_data_6(std::string name_, int age_, json metadata_) + : name(std::move(name_)) + , age(age_) + , metadata(std::move(metadata_)) + {} + + std::string getName() const + { + return name; + } + int getAge() const + { + return age; + } + json getMetadata() const + { + return metadata; + } +}; + +// NOLINTNEXTLINE(misc-use-internal-linkage) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(person_without_private_data_6, "json_age", age, "json_name", name, "json_metadata", metadata) + +class derived_person_without_private_data_6 : public person_without_private_data_6 +{ + public: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_without_private_data_6& rhs) const + { + return person_without_private_data_6::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_without_private_data_6() = default; + derived_person_without_private_data_6(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_without_private_data_6(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + std::string getHairColor() const + { + return hair_color; + } +}; + +// NOLINTNEXTLINE(misc-use-internal-linkage) +NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(derived_person_without_private_data_6, person_without_private_data_6, "json_hair_color", hair_color) + class person_with_private_alphabet { public: @@ -433,31 +685,97 @@ class person_without_default_constructor_2 // NOLINTNEXTLINE(misc-use-internal-linkage) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(person_without_default_constructor_2, name, age) -class derived_person_only_serialize_public : public person_without_default_constructor_1 +class person_without_default_constructor_3 +{ + public: + std::string name; + int age; + + bool operator==(const person_without_default_constructor_3& other) const + { + return name == other.name && age == other.age; + } + + person_without_default_constructor_3(std::string name_, int age_) + : name{std::move(name_)} + , age{age_} + {} + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(person_without_default_constructor_3, "json_name", name, "json_age", age) +}; + +class person_without_default_constructor_4 +{ + public: + std::string name; + int age; + + bool operator==(const person_without_default_constructor_4& other) const + { + return name == other.name && age == other.age; + } + + person_without_default_constructor_4(std::string name_, int age_) + : name{std::move(name_)} + , age{age_} + {} +}; + +// NOLINTNEXTLINE(misc-use-internal-linkage) +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(person_without_default_constructor_4, "json_name", name, "json_age", age) + +class derived_person_only_serialize_public_1 : public person_without_default_constructor_1 { public: std::string hair_color; - derived_person_only_serialize_public(std::string name_, int age_, std::string hair_color_) + derived_person_only_serialize_public_1(std::string name_, int age_, std::string hair_color_) : person_without_default_constructor_1(std::move(name_), age_) , hair_color(std::move(hair_color_)) {} }; // NOLINTNEXTLINE(misc-use-internal-linkage) -NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(derived_person_only_serialize_public, person_without_default_constructor_1, hair_color) +NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(derived_person_only_serialize_public_1, person_without_default_constructor_1, hair_color) + +class derived_person_only_serialize_public_3 : public person_without_default_constructor_3 +{ + public: + std::string hair_color; + + derived_person_only_serialize_public_3(std::string name_, int age_, std::string hair_color_) + : person_without_default_constructor_3(std::move(name_), age_) + , hair_color(std::move(hair_color_)) + {} +}; + +// NOLINTNEXTLINE(misc-use-internal-linkage) +NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(derived_person_only_serialize_public_3, person_without_default_constructor_3, "json_hair_color", hair_color) -class derived_person_only_serialize_private : person_without_default_constructor_1 +class derived_person_only_serialize_private_1 : person_without_default_constructor_1 { private: std::string hair_color; public: - derived_person_only_serialize_private(std::string name_, int age_, std::string hair_color_) + derived_person_only_serialize_private_1(std::string name_, int age_, std::string hair_color_) : person_without_default_constructor_1(std::move(name_), age_) , hair_color(std::move(hair_color_)) {} - NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(derived_person_only_serialize_private, person_without_default_constructor_1, hair_color) + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(derived_person_only_serialize_private_1, person_without_default_constructor_1, hair_color) +}; + +class derived_person_only_serialize_private_3 : person_without_default_constructor_3 +{ + private: + std::string hair_color; + public: + derived_person_only_serialize_private_3(std::string name_, int age_, std::string hair_color_) + : person_without_default_constructor_3(std::move(name_), age_) + , hair_color(std::move(hair_color_)) + {} + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(derived_person_only_serialize_private_3, person_without_default_constructor_3, "json_hair_color", hair_color) }; } // namespace persons @@ -532,6 +850,58 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TY } } +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES", T, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + persons::person_with_private_data_3, + persons::person_without_private_data_4, + persons::person_without_private_data_5) +{ + SECTION("person") + { + // serialization + T p1("Erik", 1, {{"haircuts", 2}}); + CHECK(json(p1).dump() == "{\"json_age\":1,\"json_metadata\":{\"haircuts\":2},\"json_name\":\"Erik\"}"); + + // deserialization + auto p2 = json(p1).get(); + CHECK(p2 == p1); + + // roundtrip + CHECK(T(json(p1)) == p1); + CHECK(json(T(json(p1))) == json(p1)); + + // check exception in case of missing field + json j = json(p1); + j.erase("json_age"); + CHECK_THROWS_WITH_AS(j.get(), "[json.exception.out_of_range.403] key 'json_age' not found", json::out_of_range); + } +} + +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES", T, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + persons::derived_person_with_private_data_3, + persons::derived_person_without_private_data_4, + persons::derived_person_without_private_data_5) +{ + SECTION("person") + { + // serialization + T p1("Erik", 1, {{"haircuts", 2}}, "red"); + CHECK(json(p1).dump() == "{\"json_age\":1,\"json_hair_color\":\"red\",\"json_metadata\":{\"haircuts\":2},\"json_name\":\"Erik\"}"); + + // deserialization + auto p2 = json(p1).get(); + CHECK(p2 == p1); + + // roundtrip + CHECK(T(json(p1)) == p1); + CHECK(json(T(json(p1))) == json(p1)); + + // check exception in case of missing field + json j = json(p1); + j.erase("json_age"); + CHECK_THROWS_WITH_AS(j.get(), "[json.exception.out_of_range.403] key 'json_age' not found", json::out_of_range); + } +} + TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) std::pair, std::pair, @@ -629,7 +999,77 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TY } } -TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES", T, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + persons::person_with_private_data_4, + persons::person_without_private_data_6) +{ + SECTION("person with default values") + { + // serialization of default constructed object + T p0; + CHECK(json(p0).dump() == "{\"json_age\":0,\"json_metadata\":null,\"json_name\":\"\"}"); + + // serialization + T p1("Erik", 1, {{"haircuts", 2}}); + CHECK(json(p1).dump() == "{\"json_age\":1,\"json_metadata\":{\"haircuts\":2},\"json_name\":\"Erik\"}"); + + // deserialization + auto p2 = json(p1).get(); + CHECK(p2 == p1); + + // roundtrip + CHECK(T(json(p1)) == p1); + CHECK(json(T(json(p1))) == json(p1)); + + // check default value in case of missing field + json j = json(p1); + j.erase("json_name"); + j.erase("json_age"); + j.erase("json_metadata"); + T p3 = j.get(); + CHECK(p3.getName() == ""); + CHECK(p3.getAge() == 0); + CHECK(p3.getMetadata() == nullptr); + } +} + +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES", T, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + persons::derived_person_with_private_data_4, + persons::derived_person_without_private_data_6) +{ + SECTION("derived person with default values") + { + // serialization of default constructed object + T p0; + CHECK(json(p0).dump() == "{\"json_age\":0,\"json_hair_color\":\"blue\",\"json_metadata\":null,\"json_name\":\"\"}"); + + // serialization + T p1("Erik", 1, {{"haircuts", 2}}, "red"); + CHECK(json(p1).dump() == "{\"json_age\":1,\"json_hair_color\":\"red\",\"json_metadata\":{\"haircuts\":2},\"json_name\":\"Erik\"}"); + + // deserialization + auto p2 = json(p1).get(); + CHECK(p2 == p1); + + // roundtrip + CHECK(T(json(p1)) == p1); + CHECK(json(T(json(p1))) == json(p1)); + + // check default value in case of missing field + json j = json(p1); + j.erase("json_name"); + j.erase("json_age"); + j.erase("json_metadata"); + j.erase("json_hair_color"); + T p3 = j.get(); + CHECK(p3.getName() == ""); + CHECK(p3.getAge() == 0); + CHECK(p3.getMetadata() == nullptr); + CHECK(p3.getHairColor() == "blue"); + } +} + +TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization, bugprone-throwing-static-initialization) std::pair, std::pair, std::pair, @@ -648,7 +1088,7 @@ TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/priv } } -TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) +TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization, bugprone-throwing-static-initialization) std::pair, std::pair, std::pair, @@ -678,11 +1118,33 @@ TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHM } } +TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES", T, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + persons::person_without_default_constructor_3, + persons::person_without_default_constructor_4) +{ + SECTION("person") + { + { + // serialization of a single object + T person{"Erik", 1}; + CHECK(json(person).dump() == "{\"json_age\":1,\"json_name\":\"Erik\"}"); + + // serialization of a container with objects + std::vector const two_persons + { + {"Erik", 1}, + {"Kyle", 2} + }; + CHECK(json(two_persons).dump() == "[{\"json_age\":1,\"json_name\":\"Erik\"},{\"json_age\":2,\"json_name\":\"Kyle\"}]"); + } + } +} + TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) - std::pair, - std::pair, - std::pair, - std::pair) + std::pair, + std::pair, + std::pair, + std::pair) { using Json = typename Pair::first_type; using T = typename Pair::second_type; @@ -707,3 +1169,59 @@ TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHM R"([{"age":1,"hair_color":"brown","name":"Erik"},{"age":2,"hair_color":"black","name":"Kyle"}])")); } } + +namespace emptys +{ +class empty_intrusive +{ + NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE(empty_intrusive) +}; + +class empty_non_intrusive +{ +}; + +// NOLINTNEXTLINE(misc-use-internal-linkage) +NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE(empty_non_intrusive) + +} // namespace emptys + +TEST_CASE_TEMPLATE("Serialization/deserialization of classes with no member variables", T, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + emptys::empty_intrusive, + emptys::empty_non_intrusive) +{ + SECTION("empty") + { + { + T empty; + std::string const s = json(empty).dump(); + CHECK(s == "{}"); + + nlohmann::json const json_empty = nlohmann::json::parse(s); + T empty2; + json_empty.get_to(empty2); + } + } +} + + TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES", T, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + persons::derived_person_only_serialize_public_3, + persons::derived_person_only_serialize_private_3) + { + SECTION("derived person only serialize") + { + { + // serialization of a single object + T person{"Erik", 1, "brown"}; + CHECK(json(person).dump() == "{\"json_age\":1,\"json_hair_color\":\"brown\",\"json_name\":\"Erik\"}"); + + // serialization of a container with objects + std::vector const two_persons + { + {"Erik", 1, "brown"}, + {"Kyle", 2, "black"} + }; + CHECK(json(two_persons).dump() == "[{\"json_age\":1,\"json_hair_color\":\"brown\",\"json_name\":\"Erik\"},{\"json_age\":2,\"json_hair_color\":\"black\",\"json_name\":\"Kyle\"}]"); + } + } + }