mirror of
https://github.com/nlohmann/json.git
synced 2026-09-01 14:07:14 +00:00
Compare commits
36
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8a0990582 | ||
|
|
7e87e5920f | ||
|
|
0b28c63bad | ||
|
|
4dcd45b26d | ||
|
|
9d83673263 | ||
|
|
d969eef216 | ||
|
|
ca76c37650 | ||
|
|
fe2bcc080f | ||
|
|
c60217e801 | ||
|
|
6ba332c7df | ||
|
|
e9c3985f0a | ||
|
|
b630f5e9c7 | ||
|
|
4d8e7a7210 | ||
|
|
75e8fbac32 | ||
|
|
631e667fe5 | ||
|
|
d0a43141ea | ||
|
|
ecff144b3a | ||
|
|
855f511db4 | ||
|
|
d0de6a9111 | ||
|
|
f8e99e856c | ||
|
|
521a084827 | ||
|
|
ca91678af1 | ||
|
|
ff34a3fd2f | ||
|
|
fe0299545a | ||
|
|
366f3d26e5 | ||
|
|
7c9208bfb3 | ||
|
|
bb60941f0e | ||
|
|
3b0dd69928 | ||
|
|
c05c5e229b | ||
|
|
acf076a677 | ||
|
|
33edc9751c | ||
|
|
83c87cb9e0 | ||
|
|
eed1587000 | ||
|
|
c034480c22 | ||
|
|
899cf31255 | ||
|
|
c363dc3e4d |
@@ -4,28 +4,44 @@ updates:
|
||||
directory: /
|
||||
schedule:
|
||||
interval: daily
|
||||
cooldown:
|
||||
default-days: 7
|
||||
groups:
|
||||
codeql-action:
|
||||
patterns:
|
||||
- "github/codeql-action/*"
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /docs/mkdocs
|
||||
schedule:
|
||||
interval: daily
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /tools/astyle
|
||||
schedule:
|
||||
interval: daily
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /tools/generate_natvis
|
||||
schedule:
|
||||
interval: daily
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /tools/serve_header
|
||||
schedule:
|
||||
interval: daily
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /cmake/requirements
|
||||
schedule:
|
||||
interval: daily
|
||||
cooldown:
|
||||
default-days: 7
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -38,14 +38,14 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
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@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/autobuild@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
|
||||
uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -47,7 +47,10 @@ jobs:
|
||||
|
||||
var hasPatch = artifacts.data.artifacts.some((artifact) => artifact.name == "amalgamation-patch");
|
||||
core.setOutput('has_patch', String(hasPatch));
|
||||
- run: unzip pr.zip
|
||||
# Extract the untrusted PR artifact into a dedicated empty directory and
|
||||
# read only the two expected files by fixed path afterwards. This avoids a
|
||||
# malicious archive overwriting workspace files or escaping via ../ paths.
|
||||
- run: unzip -o pr.zip -d ./pr_artifact
|
||||
|
||||
- name: 'Comment on PR'
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
@@ -55,8 +58,19 @@ jobs:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
var fs = require('fs');
|
||||
const author = fs.readFileSync('./author')
|
||||
const issue_number = Number(fs.readFileSync('./number'));
|
||||
// Both values come from a fork-triggered workflow and are therefore
|
||||
// attacker-controlled. Validate them strictly before use to prevent
|
||||
// Markdown/mention injection and bogus REST API filters.
|
||||
const author = fs.readFileSync('./pr_artifact/author', 'utf8').trim();
|
||||
if (!/^[A-Za-z0-9-]{1,39}$/.test(author)) {
|
||||
core.setFailed(`Refusing to proceed: untrusted author value '${author}' is not a valid GitHub username.`);
|
||||
return;
|
||||
}
|
||||
const issue_number = Number(fs.readFileSync('./pr_artifact/number', 'utf8').trim());
|
||||
if (!Number.isInteger(issue_number) || issue_number <= 0) {
|
||||
core.setFailed('Refusing to proceed: untrusted PR number is not a positive integer.');
|
||||
return;
|
||||
}
|
||||
const opts = github.rest.issues.listForRepo.endpoint.merge({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -41,12 +41,23 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
# Scan code using project's configuration on https://semgrep.dev/manage
|
||||
- uses: returntocorp/semgrep-action@713efdd345f3035192eaa63f56867b88e63e4e5d
|
||||
with:
|
||||
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
|
||||
publishDeployment: ${{ secrets.SEMGREP_DEPLOYMENT_ID }}
|
||||
generateSarif: "1"
|
||||
# The former returntocorp/semgrep-action is deprecated (the org was renamed
|
||||
# to semgrep/*); the maintained approach is to install the CLI and invoke
|
||||
# it directly. We use `semgrep scan` (not `semgrep ci`, which requires a
|
||||
# login token): with no SEMGREP_APP_TOKEN configured this is exactly what
|
||||
# the old action fell back to, running community rules with no token.
|
||||
# SEMGREP_APP_TOKEN is still passed through so registry auth works if a
|
||||
# token is ever added.
|
||||
- name: Install Semgrep
|
||||
run: python3 -m pip install --user semgrep==1.168.0
|
||||
|
||||
# `semgrep scan --sarif` always exits 0 even with findings; continue-on-error
|
||||
# is a safety net so the SARIF upload still runs if the scan itself errors.
|
||||
- name: Run Semgrep
|
||||
run: semgrep scan --config auto --sarif --output=semgrep.sarif
|
||||
continue-on-error: true
|
||||
env:
|
||||
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
|
||||
|
||||
# Upload SARIF file generated in previous step
|
||||
- name: Upload SARIF file
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -33,11 +33,21 @@ jobs:
|
||||
|
||||
ci_infer:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/nlohmann/json-ci:v2.4.0
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Install Infer
|
||||
run: |
|
||||
wget -q -O - "https://github.com/facebook/infer/releases/download/v1.3.0/infer-linux-x86_64-v1.3.0.tar.xz" | sudo tar -C /opt -xJ
|
||||
sudo ln -s /opt/infer-linux-x86_64-v1.3.0/bin/infer /usr/local/bin/infer
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -50,7 +60,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@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -108,7 +118,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -143,11 +153,30 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
compiler: ['4.8', '4.9', '5', '6']
|
||||
container: ghcr.io/nlohmann/json-ci:v2.4.0
|
||||
# official gcc:4.8/4.9/5/6 images fail to check out code (too old for
|
||||
# actions/checkout); install the old compilers on top of official ubuntu:20.04
|
||||
# instead, mirroring what the (now retired) custom json-ci image did.
|
||||
container: ubuntu:20.04
|
||||
steps:
|
||||
- name: Install g++-${{ matrix.compiler }}
|
||||
run: |
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends software-properties-common ca-certificates gnupg make git
|
||||
add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu/ bionic main"
|
||||
apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu/ bionic universe"
|
||||
apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu/ xenial main"
|
||||
apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu/ xenial universe"
|
||||
apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu/ xenial-updates main"
|
||||
apt-add-repository -y "deb http://archive.ubuntu.com/ubuntu/ xenial-updates universe"
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends g++-${{ matrix.compiler }}
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4
|
||||
- name: Run CMake
|
||||
run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -234,11 +263,22 @@ jobs:
|
||||
|
||||
ci_cuda_example:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/nlohmann/json-ci:v2.4.0
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# 11.8.0: newest pre-C++20 CUDA release, exercises the C++17 fallback
|
||||
# path (tests/cuda_example/CMakeLists.txt picks the standard per nvcc
|
||||
# version); 12.1.1: permanent regression guard for #3907 (nvcc 12.0/12.1
|
||||
# choke on enable_borrowed_range at C++20, fixed in 12.2); 12.6.3: recent
|
||||
# CUDA/C++20 coverage.
|
||||
cuda: ['11.8.0', '12.1.1', '12.6.3']
|
||||
container: nvidia/cuda:${{ matrix.cuda }}-devel-ubuntu22.04
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -276,17 +316,22 @@ jobs:
|
||||
|
||||
ci_icpc:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/nlohmann/json-ci:v2.2.0
|
||||
# Intel discontinued the classic icc/icpc compiler in oneAPI 2024.0; this is
|
||||
# Intel's own last officially published image that still includes it.
|
||||
container: intel/oneapi-hpckit:2023.2.1-devel-ubuntu22.04
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f5b8fbb4d77cec1acc5a5f9f0df4beffaf5d98d9 # v4.3.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
run: |
|
||||
. /opt/intel/oneapi/setvars.sh
|
||||
cmake --build build --target ci_icpc
|
||||
# No need to source setvars.sh here: unlike the old custom image, this
|
||||
# official image already has the oneAPI environment (icc/icpc on PATH)
|
||||
# baked in, and re-sourcing it fails with "already been run" (exit 3).
|
||||
run: cmake --build build --target ci_icpc
|
||||
|
||||
ci_icpx:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -316,7 +361,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -339,7 +384,7 @@ jobs:
|
||||
target: [ci_test_examples, ci_test_build_documentation]
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
|
||||
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ Files: include/nlohmann/thirdparty/hedley.hpp
|
||||
Copyright: 2016-2021 Evan Nemerson <evan@nemerson.com>
|
||||
License: CC0
|
||||
|
||||
Files: include/nlohmann/detail/meta/cpp_future.hpp
|
||||
Copyright: 2013-2026 Niels Lohmann <https://nlohmann.me> and 2018 The Abseil Authors
|
||||
License: MIT AND Apache-2.0
|
||||
|
||||
Files: tests/thirdparty/doctest/*
|
||||
Copyright: 2016-2023 Viktor Kirilov
|
||||
License: MIT
|
||||
|
||||
+6
-2
@@ -669,7 +669,6 @@ add_custom_target(ci_test_compiler_default
|
||||
add_custom_target(ci_cuda_example
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DCMAKE_CUDA_HOST_COMPILER=g++-8
|
||||
-S${PROJECT_SOURCE_DIR}/tests/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_cuda_example
|
||||
)
|
||||
@@ -720,6 +719,11 @@ add_custom_target(ci_icpx
|
||||
# to zero and does not honor NaN ordering; -Kieee restores strict IEEE 754 behavior
|
||||
# (needed for the dtoa/grisu and NaN-comparison code paths).
|
||||
#
|
||||
# -tp=px pins the target processor to the generic x86-64 baseline (SSE2-only) to avoid
|
||||
# a nvc++ 25.5 / LLVM issue: when nvc++ auto-detects -tp from the runner's CPU (e.g. -tp znver4),
|
||||
# certain attribute combinations trigger an llc instruction-selection crash on std::ldexp<unsigned>.
|
||||
# Pinning to px removes this variability and is robust to future llc/nvc++ updates.
|
||||
#
|
||||
# The following tests are excluded as they trigger known nvc++ 25.5 defects (not
|
||||
# library bugs); see https://github.com/nlohmann/json for tracking. Only the
|
||||
# affected language-standard variants are excluded so coverage is otherwise kept:
|
||||
@@ -733,7 +737,7 @@ add_custom_target(ci_nvhpc
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DCMAKE_C_COMPILER=nvc -DCMAKE_CXX_COMPILER=nvc++
|
||||
-DCMAKE_CXX_FLAGS=-Kieee
|
||||
-DCMAKE_CXX_FLAGS="-Kieee;-tp=px"
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_nvhpc
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_nvhpc
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
# -Wno-extra-semi-stmt The library uses assert which triggers this warning.
|
||||
# -Wno-padded We do not care about padding warnings.
|
||||
# -Wno-covered-switch-default All switches list all cases and a default case.
|
||||
# -Wno-unsafe-buffer-usage Otherwise Doctest would not compile.
|
||||
# -Wno-missing-noreturn We found no way to silence this warning otherwise, see PR #4871
|
||||
# -Wno-unsafe-buffer-usage Pervasive: the library's own low-level numeric/buffer code
|
||||
# (to_chars, serializer, lexer, binary reader/writer, input
|
||||
# adapters, json_pointer) plus vendored Doctest itself (~208
|
||||
# distinct sites measured 2026-07-08 on clang trunk) all use
|
||||
# raw pointer arithmetic / libc string calls by necessity.
|
||||
|
||||
set(CLANG_CXXFLAGS
|
||||
-Werror
|
||||
@@ -18,5 +21,4 @@ set(CLANG_CXXFLAGS
|
||||
-Wno-padded
|
||||
-Wno-covered-switch-default
|
||||
-Wno-unsafe-buffer-usage
|
||||
-Wno-missing-noreturn
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"archive": "JSON_for_Modern_C++.tgz",
|
||||
"author": {
|
||||
"name": "Niels Lohmann",
|
||||
"link": "https://twitter.com/nlohmann"
|
||||
"link": "https://nlohmann.me"
|
||||
},
|
||||
"aliases": ["nlohmann/json"]
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ static bool accept(InputType&& i,
|
||||
const bool ignore_trailing_commas = false);
|
||||
|
||||
// (2)
|
||||
template<typename IteratorType>
|
||||
static bool accept(IteratorType first, IteratorType last,
|
||||
template<typename IteratorType, typename SentinelType = IteratorType>
|
||||
static bool accept(IteratorType first, SentinelType last,
|
||||
const bool ignore_comments = false,
|
||||
const bool ignore_trailing_commas = false);
|
||||
```
|
||||
@@ -17,10 +17,11 @@ static bool accept(IteratorType first, IteratorType last,
|
||||
Checks whether the input is valid JSON.
|
||||
|
||||
1. Reads from a compatible input.
|
||||
2. Reads from a pair of character iterators
|
||||
2. Reads from a pair of character iterators, or an iterator and a sentinel of a different type (C++20 ranges support)
|
||||
|
||||
The value_type of the iterator must be an integral type with a size of 1, 2, or 4 bytes, which will be interpreted
|
||||
respectively as UTF-8, UTF-16, and UTF-32.
|
||||
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
|
||||
the iterator type with `operator!=`.
|
||||
|
||||
Unlike the [`parse()`](parse.md) function, this function neither throws an exception in case of invalid JSON input
|
||||
(i.e., a parse error) nor creates diagnostic information.
|
||||
@@ -35,7 +36,8 @@ Unlike the [`parse()`](parse.md) function, this function neither throws an excep
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters (throws if null)
|
||||
- a `std::string`
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type, for instance.
|
||||
@@ -43,6 +45,12 @@ Unlike the [`parse()`](parse.md) function, this function neither throws an excep
|
||||
- a pair of `std::string::iterator` or `std::vector<std::uint8_t>::iterator`
|
||||
- a pair of pointers such as `ptr` and `ptr + len`
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance.
|
||||
|
||||
- a custom sentinel type for C++20 ranges
|
||||
- `std::counted_iterator` with a different sentinel type
|
||||
|
||||
## Parameters
|
||||
|
||||
`i` (in)
|
||||
@@ -60,7 +68,7 @@ Unlike the [`parse()`](parse.md) function, this function neither throws an excep
|
||||
: iterator to the start of the character range
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of the character range
|
||||
: iterator to the end of the character range, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
## Return value
|
||||
|
||||
@@ -109,7 +117,9 @@ A UTF-8 byte order mark is silently ignored.
|
||||
- Added in version 3.0.0.
|
||||
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
||||
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
|
||||
- Added `ignore_trailing_commas` in version 3.12.x.
|
||||
- Added `ignore_trailing_commas` in version 3.13.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ This function is only needed to express two edge cases that cannot be realized w
|
||||
|
||||
- [`basic_json(initializer_list_t)`](basic_json.md) - create a JSON value from an initializer list
|
||||
- [`object`](object.md) - create a JSON object value from an initializer list
|
||||
- [Creating JSON values](../../features/creating_values.md) - the article on creating JSON values
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -82,7 +82,13 @@ basic_json(basic_json&& other) noexcept;
|
||||
4. This is a constructor for existing `basic_json` types. It does not hijack copy/move constructors, since the parameter
|
||||
has different template arguments than the current ones.
|
||||
|
||||
The constructor tries to convert the internal `m_value` of the parameter.
|
||||
The constructor tries to convert the internal `m_value` of the parameter. Each member value (object, array, string,
|
||||
etc.) is serialized via the corresponding `to_json()` overload. For objects and strings, the conversion requires
|
||||
that the *target* `basic_json` type's `object_t::key_type` (or `string_t`) be directly constructible from the
|
||||
*source* type's corresponding member type via `is_constructible`. If this requirement is not met, the conversion
|
||||
does not fail to compile; instead, it silently falls back to the array-conversion path, which represents objects
|
||||
as arrays of `[key, value]` pairs and strings as arrays of character codes. This is a known limitation tracked in
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425).
|
||||
|
||||
5. Creates a JSON value of type array or object from the passed initializer list `init`. In case `type_deduction` is
|
||||
`#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init`
|
||||
@@ -109,7 +115,22 @@ basic_json(basic_json&& other) noexcept;
|
||||
|
||||
Function [`array()`](array.md) and [`object()`](object.md) force array and object creation from initializer lists,
|
||||
respectively.
|
||||
|
||||
|
||||
!!! warning "Brace initialization yields arrays"
|
||||
|
||||
Because this constructor takes an `initializer_list_t`, brace-initializing a `json`/`ordered_json` from
|
||||
another `json` value wraps it in a single-element array rather than copying it:
|
||||
|
||||
```cpp
|
||||
json j1 = "hello";
|
||||
json j2{j1}; // [!] j2 is ["hello"], NOT a copy of j1
|
||||
json j3(j1); // j3 is "hello" -- parentheses copy as expected
|
||||
```
|
||||
|
||||
See the FAQ entry on [brace initialization](../../home/faq.md#brace-initialization-yields-arrays) for the
|
||||
full explanation, an opt-in macro to change this behavior, and how to explicitly create a single-element
|
||||
array (`json::array({value})`) if that is what you want.
|
||||
|
||||
6. Constructs a JSON array value by creating `cnt` copies of a passed value. In case `cnt` is `0`, an empty array is
|
||||
created.
|
||||
|
||||
@@ -146,6 +167,11 @@ basic_json(basic_json&& other) noexcept;
|
||||
|
||||
- `BasicJsonType` is a `basic_json` type.
|
||||
- `BasicJsonType` has different template arguments than `basic_json_t`.
|
||||
|
||||
**Note:** For cross-`basic_json` conversions to produce correct results, the target `basic_json`'s
|
||||
`object_t::key_type` and `string_t` must be directly constructible from the source `basic_json`'s
|
||||
corresponding types. See the description of overload (4) above for details on what happens when
|
||||
this requirement is not met.
|
||||
|
||||
`U`:
|
||||
: `uncvref_t<CompatibleType>`
|
||||
|
||||
@@ -37,12 +37,52 @@ represent a byte array in modern C++.
|
||||
`BinaryType`
|
||||
: container type to store arrays
|
||||
|
||||
Although not formally expressed as a C++ concept, `BinaryType` must be default-constructible,
|
||||
copy/move-constructible, and support `push_back()`, `.data()`, and `.size()`, because
|
||||
[`byte_container_with_subtype`](../byte_container_with_subtype/index.md) derives directly from it. Its
|
||||
`value_type` must additionally be exactly one byte wide (e.g., `std::uint8_t`/`char`/`std::byte`): the binary
|
||||
serializers (CBOR, MessagePack, BSON, UBJSON) read and write the container's raw bytes via
|
||||
`reinterpret_cast`, which is only correct for byte-sized elements -- a container like
|
||||
`#!cpp std::vector<std::intptr_t>` will not work as `BinaryType`.
|
||||
|
||||
## Notes
|
||||
|
||||
#### Default type
|
||||
|
||||
The default values for `BinaryType` is `#!cpp std::vector<std::uint8_t>`.
|
||||
|
||||
#### Custom BinaryType behavior
|
||||
|
||||
When a custom `BinaryType` is configured (other than the default `#!cpp std::vector<std::uint8_t>`), you can assign
|
||||
values of that type directly to a `basic_json` instance, and they will automatically be recognized as binary values
|
||||
rather than arrays:
|
||||
|
||||
```cpp
|
||||
using custom_json = nlohmann::basic_json<
|
||||
nlohmann::ordered_map, // ObjectType
|
||||
std::vector, // ArrayType
|
||||
std::string, // StringType
|
||||
bool, // BooleanType
|
||||
std::int64_t, // NumberIntegerType
|
||||
std::uint64_t, // NumberUnsignedType
|
||||
double, // NumberFloatType
|
||||
std::allocator, // AllocatorType
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::byte> // Custom BinaryType
|
||||
>;
|
||||
|
||||
std::vector<std::byte> data{std::byte{1}, std::byte{2}, std::byte{3}};
|
||||
custom_json j = data; // Creates a binary value, not an array
|
||||
assert(j.is_binary());
|
||||
|
||||
// Round-tripping works seamlessly
|
||||
auto extracted = j.get<std::vector<std::byte>>();
|
||||
assert(extracted == data);
|
||||
```
|
||||
|
||||
This automatic type detection is a convenience feature that only applies to custom (non-default) `BinaryType` configurations.
|
||||
The default `nlohmann::json` continues to treat `#!cpp std::vector<std::uint8_t>` as arrays for backward compatibility.
|
||||
|
||||
#### Storage
|
||||
|
||||
Binary Arrays are stored as pointers in a `basic_json` type. That is, for any access to array values, a pointer of the
|
||||
|
||||
@@ -75,6 +75,7 @@ Binary values are serialized as an object containing two keys:
|
||||
|
||||
- [to_string](to_string.md) returns a string representation of a JSON value
|
||||
- [operator<<](../operator_ltlt.md) serialize to stream
|
||||
- [Serialization](../../features/serialization.md) - the serialization article
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ Logarithmic in the size of the container, O(log(`size()`)).
|
||||
|
||||
- [emplace_back](emplace_back.md) add a value to an array
|
||||
- [insert](insert.md) add values to an array/object
|
||||
- [Modifying values](../../features/modifying_values.md) - the article on modifying values
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ Amortized constant.
|
||||
|
||||
- [operator+=](operator+=.md) add a value to an array/object
|
||||
- [push_back](push_back.md) add a value to an array/object
|
||||
- [Modifying values](../../features/modifying_values.md) - the article on modifying values
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -206,6 +206,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
|
||||
- [clear](clear.md) clears the contents
|
||||
- [insert](insert.md) add values to an array/object
|
||||
- [Modifying values](../../features/modifying_values.md) - the article on modifying values
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ std::string format_as(const BasicJsonType& j)
|
||||
|
||||
- [dump](dump.md)
|
||||
- [std::formatter<basic_json>](std_formatter.md) - the `std::format` (C++20) equivalent
|
||||
- [Serialization](../../features/serialization.md) - the serialization article
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.x.
|
||||
- Added in version 3.13.0.
|
||||
|
||||
@@ -7,8 +7,8 @@ static basic_json from_bjdata(InputType&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
// (2)
|
||||
template<typename IteratorType>
|
||||
static basic_json from_bjdata(IteratorType first, IteratorType last,
|
||||
template<typename IteratorType, typename SentinelType = IteratorType>
|
||||
static basic_json from_bjdata(IteratorType first, SentinelType last,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
```
|
||||
@@ -16,7 +16,7 @@ static basic_json from_bjdata(IteratorType first, IteratorType last,
|
||||
Deserializes a given input to a JSON value using the BJData (Binary JData) serialization format.
|
||||
|
||||
1. Reads from a compatible input.
|
||||
2. Reads from an iterator range.
|
||||
2. Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).
|
||||
|
||||
The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/bjdata.md).
|
||||
|
||||
@@ -29,11 +29,16 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
- a `FILE` pointer
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance a
|
||||
custom sentinel type for C++20 ranges
|
||||
|
||||
## Parameters
|
||||
|
||||
`i` (in)
|
||||
@@ -43,7 +48,7 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
: iterator to the start of the input
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of the input
|
||||
: iterator to the end of the input, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
`strict` (in)
|
||||
: whether to expect the input to be consumed until EOF (`#!cpp true` by default)
|
||||
@@ -101,3 +106,5 @@ Linear in the size of the input.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.11.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
@@ -7,8 +7,8 @@ static basic_json from_bson(InputType&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
// (2)
|
||||
template<typename IteratorType>
|
||||
static basic_json from_bson(IteratorType first, IteratorType last,
|
||||
template<typename IteratorType, typename SentinelType = IteratorType>
|
||||
static basic_json from_bson(IteratorType first, SentinelType last,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
```
|
||||
@@ -16,7 +16,7 @@ static basic_json from_bson(IteratorType first, IteratorType last,
|
||||
Deserializes a given input to a JSON value using the BSON (Binary JSON) serialization format.
|
||||
|
||||
1. Reads from a compatible input.
|
||||
2. Reads from an iterator range.
|
||||
2. Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).
|
||||
|
||||
The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/bson.md).
|
||||
|
||||
@@ -29,11 +29,16 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
- a `FILE` pointer
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance a
|
||||
custom sentinel type for C++20 ranges
|
||||
|
||||
## Parameters
|
||||
|
||||
`i` (in)
|
||||
@@ -43,7 +48,7 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
: iterator to the start of the input
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of the input
|
||||
: iterator to the end of the input, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
`strict` (in)
|
||||
: whether to expect the input to be consumed until EOF (`#!cpp true` by default)
|
||||
@@ -101,6 +106,8 @@ Linear in the size of the input.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.4.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ static basic_json from_cbor(InputType&& i,
|
||||
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error);
|
||||
|
||||
// (2)
|
||||
template<typename IteratorType>
|
||||
static basic_json from_cbor(IteratorType first, IteratorType last,
|
||||
template<typename IteratorType, typename SentinelType = IteratorType>
|
||||
static basic_json from_cbor(IteratorType first, SentinelType last,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true,
|
||||
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error);
|
||||
@@ -19,7 +19,7 @@ static basic_json from_cbor(IteratorType first, IteratorType last,
|
||||
Deserializes a given input to a JSON value using the CBOR (Concise Binary Object Representation) serialization format.
|
||||
|
||||
1. Reads from a compatible input.
|
||||
2. Reads from an iterator range.
|
||||
2. Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).
|
||||
|
||||
The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/cbor.md).
|
||||
|
||||
@@ -32,11 +32,16 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
- a `FILE` pointer
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance a
|
||||
custom sentinel type for C++20 ranges
|
||||
|
||||
## Parameters
|
||||
|
||||
`i` (in)
|
||||
@@ -46,7 +51,7 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
: iterator to the start of the input
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of the input
|
||||
: iterator to the end of the input, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
`strict` (in)
|
||||
: whether to expect the input to be consumed until EOF (`#!cpp true` by default)
|
||||
@@ -111,6 +116,8 @@ Linear in the size of the input.
|
||||
- Changed to consume input adapters, removed `start_index` parameter, and added `strict` parameter in version 3.0.0.
|
||||
- Added `allow_exceptions` parameter in version 3.2.0.
|
||||
- Added `tag_handler` parameter in version 3.9.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ static basic_json from_msgpack(InputType&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
// (2)
|
||||
template<typename IteratorType>
|
||||
static basic_json from_msgpack(IteratorType first, IteratorType last,
|
||||
template<typename IteratorType, typename SentinelType = IteratorType>
|
||||
static basic_json from_msgpack(IteratorType first, SentinelType last,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
```
|
||||
@@ -16,7 +16,7 @@ static basic_json from_msgpack(IteratorType first, IteratorType last,
|
||||
Deserializes a given input to a JSON value using the MessagePack serialization format.
|
||||
|
||||
1. Reads from a compatible input.
|
||||
2. Reads from an iterator range.
|
||||
2. Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).
|
||||
|
||||
The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/messagepack.md).
|
||||
|
||||
@@ -29,11 +29,16 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
- a `FILE` pointer
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance a
|
||||
custom sentinel type for C++20 ranges
|
||||
|
||||
## Parameters
|
||||
|
||||
`i` (in)
|
||||
@@ -43,7 +48,7 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
: iterator to the start of the input
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of the input
|
||||
: iterator to the end of the input, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
`strict` (in)
|
||||
: whether to expect the input to be consumed until EOF (`#!cpp true` by default)
|
||||
@@ -103,6 +108,8 @@ Linear in the size of the input.
|
||||
- Parameter `start_index` since version 2.1.1.
|
||||
- Changed to consume input adapters, removed `start_index` parameter, and added `strict` parameter in version 3.0.0.
|
||||
- Added `allow_exceptions` parameter in version 3.2.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ static basic_json from_ubjson(InputType&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
// (2)
|
||||
template<typename IteratorType>
|
||||
static basic_json from_ubjson(IteratorType first, IteratorType last,
|
||||
template<typename IteratorType, typename SentinelType = IteratorType>
|
||||
static basic_json from_ubjson(IteratorType first, SentinelType last,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true);
|
||||
```
|
||||
@@ -16,7 +16,7 @@ static basic_json from_ubjson(IteratorType first, IteratorType last,
|
||||
Deserializes a given input to a JSON value using the UBJSON (Universal Binary JSON) serialization format.
|
||||
|
||||
1. Reads from a compatible input.
|
||||
2. Reads from an iterator range.
|
||||
2. Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).
|
||||
|
||||
The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/ubjson.md).
|
||||
|
||||
@@ -29,11 +29,16 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
- a `FILE` pointer
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance a
|
||||
custom sentinel type for C++20 ranges
|
||||
|
||||
## Parameters
|
||||
|
||||
`i` (in)
|
||||
@@ -43,7 +48,7 @@ The exact mapping and its limitations are described on a [dedicated page](../../
|
||||
: iterator to the start of the input
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of the input
|
||||
: iterator to the end of the input, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
`strict` (in)
|
||||
: whether to expect the input to be consumed until EOF (`#!cpp true` by default)
|
||||
@@ -102,6 +107,8 @@ Linear in the size of the input.
|
||||
|
||||
- Added in version 3.1.0.
|
||||
- Added `allow_exceptions` parameter in version 3.2.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -114,6 +114,13 @@ overload (3).
|
||||
See [Number conversion](../../features/types/number_handling.md#number-conversion)
|
||||
for more information.
|
||||
|
||||
!!! note "`std::optional` conversions"
|
||||
|
||||
Prior to version 3.13.0, `#!cpp get<std::optional<T>>()` (and other conversions to `std::optional<T>`) failed to
|
||||
compile in every configuration, due to an internal implementation bug that made the `from_json` overload for
|
||||
`std::optional` unreachable regardless of the [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md)
|
||||
setting. This has been fixed.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -155,6 +162,7 @@ overload (3).
|
||||
- [get_ptr](get_ptr.md) get a pointer to the stored value
|
||||
- [get_ref](get_ref.md) get a reference to the stored value
|
||||
- [operator ValueType](operator_ValueType.md) get a value via implicit conversion
|
||||
- [Converting values](../../features/conversions.md) - the type conversions article
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ Depends on the `json_serializer<ValueType>::from_json()` implementation.
|
||||
- [get](get.md) get a value (explicit conversion)
|
||||
- [get_ref](get_ref.md) get a reference to the stored value
|
||||
- [get_ptr](get_ptr.md) get a pointer to the stored value
|
||||
- [Converting values](../../features/conversions.md) - the type conversions article
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -46,6 +46,17 @@ for (auto& [key, val] : j_object.items())
|
||||
}
|
||||
```
|
||||
|
||||
If you need to name the type of the dereferenced element explicitly (e.g., to write a standalone function that
|
||||
takes it as a parameter, or to use `items()` with `std::for_each`), use `decltype`:
|
||||
|
||||
```cpp
|
||||
using element_type = decltype(*j_object.items().begin());
|
||||
```
|
||||
|
||||
The per-element type (`iteration_proxy_value`) lives in the library's internal `detail` namespace and is
|
||||
intentionally unspecified as a stable, named type -- `decltype` is the supported way to obtain it, but its exact
|
||||
name/definition may change between versions.
|
||||
|
||||
## Return value
|
||||
|
||||
iteration proxy object wrapping the current value with an interface to use in range-based for loops
|
||||
|
||||
@@ -57,6 +57,7 @@ the initializer list constructor `basic_json(initializer_list_t, bool, value_t)`
|
||||
|
||||
- [`basic_json(initializer_list_t)`](basic_json.md) - create a JSON value from an initializer list
|
||||
- [`array`](array.md) - create a JSON array value from an initializer list
|
||||
- [Creating JSON values](../../features/creating_values.md) - the article on creating JSON values
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -63,7 +63,8 @@ behavior:
|
||||
object will agree on the name-value mappings.
|
||||
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be
|
||||
chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or
|
||||
`#!json {"key": 2}`.
|
||||
`#!json {"key": 2}`. To reject duplicate keys instead of silently resolving them one way or another, see
|
||||
[this parsing recipe](../../features/parsing/parser_callbacks.md#recipe-rejecting-duplicate-object-keys).
|
||||
- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see
|
||||
[`dump`](dump.md)) in this order. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored
|
||||
and serialized as `#!json {"a": 2, "b": 1}`.
|
||||
@@ -93,6 +94,15 @@ alphabetical order as `std::map` with `std::less` is used by default. Please not
|
||||
[RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON
|
||||
objects.
|
||||
|
||||
#### Cross-`basic_json` conversion requirements
|
||||
|
||||
When converting an object from one `basic_json` specialization to another via the
|
||||
[converting constructor](basic_json.md#overload-4), the target `object_t`'s `key_type` must be
|
||||
directly constructible from the source `basic_json`'s `string_t` type (or more generally, from the
|
||||
source object's key type). If this requirement is not met, the conversion does not fail; instead,
|
||||
the object is silently converted as an array of key-value pairs, which is incorrect. See
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -124,6 +124,15 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
filled with `#!json null`.
|
||||
- The special value `-` is treated as a synonym for the index past the end.
|
||||
|
||||
!!! note "Creating intermediate levels that don't exist yet"
|
||||
|
||||
When the JSON pointer traverses intermediate levels that don't exist at all yet (not just a missing
|
||||
leaf), each missing level is created as an array or an object depending on whether the corresponding
|
||||
pointer token parses as a non-negative integer: a numeric token creates an array, a non-numeric token
|
||||
creates an object. For example, on an initially `#!json null` value, `/foo/0/0/0` creates nested arrays,
|
||||
while `/foo/one/one/one` creates nested objects. This is not specified by the JSON Pointer RFC; it is
|
||||
this library's own, intentional disambiguation rule. See also [JSON Pointer](../../features/json_pointer.md).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: (1) access specified array element"
|
||||
@@ -251,5 +260,6 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
1. Added in version 1.0.0.
|
||||
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3)
|
||||
in version 3.11.0.
|
||||
3. Added in version 3.11.0.
|
||||
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
|
||||
already supported by [`at`](at.md), [`value`](value.md), [`find`](find.md), and other lookup functions.
|
||||
4. Added in version 2.0.0.
|
||||
|
||||
@@ -78,6 +78,7 @@ Linear in the size of the JSON value.
|
||||
## See also
|
||||
|
||||
- [get](get.md) get a value (explicit conversion)
|
||||
- [Converting values](../../features/conversions.md) - the type conversions article
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -19,10 +19,8 @@ class basic_json {
|
||||
};
|
||||
```
|
||||
|
||||
1. Compares two JSON values for inequality according to the following rules:
|
||||
- The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either operand is `NaN` and
|
||||
the other operand is either `NaN` or any other number.
|
||||
- Otherwise, returns the result of `#!cpp !(lhs == rhs)` (until C++20) or `#!cpp !(*this == rhs)` (since C++20).
|
||||
1. Compares two JSON values for inequality. Returns `#!cpp !(lhs == rhs)` (until C++20) or `#!cpp !(*this == rhs)` (since C++20).
|
||||
- This means the comparison is simply the logical negation of `operator==`, including for special values like `NaN` and `discarded`.
|
||||
|
||||
2. Compares a JSON value and a scalar or a scalar and a JSON value for inequality by converting the scalar to a JSON
|
||||
value and comparing both JSON values according to 1.
|
||||
@@ -54,13 +52,12 @@ Linear.
|
||||
|
||||
## Notes
|
||||
|
||||
!!! note "Comparing `NaN`"
|
||||
!!! note "Comparing `NaN` and `discarded`"
|
||||
|
||||
`NaN` values are unordered within the domain of numbers.
|
||||
The following comparisons all yield `#!cpp false`:
|
||||
1. Comparing a `NaN` with itself.
|
||||
2. Comparing a `NaN` with another `NaN`.
|
||||
3. Comparing a `NaN` and any other number.
|
||||
Since `operator!=` is defined as `!(a == b)`, the behavior for special values follows that of `operator==`:
|
||||
|
||||
- For `NaN` values: `NaN == NaN` yields `#!cpp false`, so `NaN != NaN` yields `#!cpp true`.
|
||||
- For `discarded` values: `discarded == x` yields `#!cpp false` for any `x`, so `discarded != x` yields `#!cpp true`.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -94,5 +91,7 @@ Linear.
|
||||
|
||||
## Version history
|
||||
|
||||
1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
||||
2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
||||
1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. Changed in version 3.13.0 to remove
|
||||
special-casing for `NaN` and `discarded` values; `operator!=` now consistently means `!(a == b)`.
|
||||
2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. Changed in version 3.13.0 to remove
|
||||
special-casing for `NaN` and `discarded` values; `operator!=` now consistently means `!(a == b)`.
|
||||
|
||||
@@ -10,8 +10,8 @@ static basic_json parse(InputType&& i,
|
||||
const bool ignore_trailing_commas = false);
|
||||
|
||||
// (2)
|
||||
template<typename IteratorType>
|
||||
static basic_json parse(IteratorType first, IteratorType last,
|
||||
template<typename IteratorType, typename SentinelType = IteratorType>
|
||||
static basic_json parse(IteratorType first, SentinelType last,
|
||||
const parser_callback_t cb = nullptr,
|
||||
const bool allow_exceptions = true,
|
||||
const bool ignore_comments = false,
|
||||
@@ -19,10 +19,11 @@ static basic_json parse(IteratorType first, IteratorType last,
|
||||
```
|
||||
|
||||
1. Deserialize from a compatible input.
|
||||
2. Deserialize from a pair of character iterators
|
||||
2. Deserialize from a pair of character iterators, or an iterator and a sentinel of a different type (C++20 ranges support)
|
||||
|
||||
The `value_type` of the iterator must be an integral type with size of 1, 2, or 4 bytes, which will be interpreted
|
||||
respectively as UTF-8, UTF-16, and UTF-32.
|
||||
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
|
||||
the iterator type with `operator!=`.
|
||||
|
||||
## Template parameters
|
||||
|
||||
@@ -34,7 +35,8 @@ static basic_json parse(IteratorType first, IteratorType last,
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters (throws if null)
|
||||
- a `std::string`
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type, for instance.
|
||||
@@ -42,6 +44,12 @@ static basic_json parse(IteratorType first, IteratorType last,
|
||||
- a pair of `std::string::iterator` or `std::vector<std::uint8_t>::iterator`
|
||||
- a pair of pointers such as `ptr` and `ptr + len`
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance.
|
||||
|
||||
- a custom sentinel type for C++20 ranges
|
||||
- `std::counted_iterator` with a different sentinel type
|
||||
|
||||
## Parameters
|
||||
|
||||
`i` (in)
|
||||
@@ -66,7 +74,7 @@ static basic_json parse(IteratorType first, IteratorType last,
|
||||
: iterator to the start of a character range
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of a character range
|
||||
: iterator to the end of a character range, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
## Return value
|
||||
|
||||
@@ -235,7 +243,9 @@ Invalid Unicode escapes and unpaired surrogates in the input are reported as
|
||||
- Overload for contiguous containers (1) added in version 2.0.3.
|
||||
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
||||
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
|
||||
- Added `ignore_trailing_commas` in version 3.12.x.
|
||||
- Added `ignore_trailing_commas` in version 3.13.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -74,4 +74,4 @@ is thrown. In any case, the original value is not changed: the patch is applied
|
||||
|
||||
- Added in version 2.0.0.
|
||||
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
||||
target location has a non-object/non-array parent in version 3.12.x.
|
||||
target location has a non-object/non-array parent in version 3.13.0.
|
||||
|
||||
@@ -71,4 +71,4 @@ function throws an exception.
|
||||
|
||||
- Added in version 3.11.0.
|
||||
- Added [`out_of_range.411`](../../home/exceptions.md#jsonexceptionout_of_range411) and stopped relying on an internal assertion when an "add" operation's
|
||||
target location has a non-object/non-array parent in version 3.12.x.
|
||||
target location has a non-object/non-array parent in version 3.13.0.
|
||||
|
||||
@@ -115,6 +115,7 @@ invalidates all iterators and all references.
|
||||
|
||||
- [emplace_back](emplace_back.md) add a value to an array
|
||||
- [operator+=](operator+=.md) add a value to an array/object
|
||||
- [Modifying values](../../features/modifying_values.md) - the article on modifying values
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ static bool sax_parse(InputType&& i,
|
||||
const bool ignore_trailing_commas = false);
|
||||
|
||||
// (2)
|
||||
template<class IteratorType, class SAX>
|
||||
static bool sax_parse(IteratorType first, IteratorType last,
|
||||
template<class IteratorType, class SAX, class SentinelType = IteratorType>
|
||||
static bool sax_parse(IteratorType first, SentinelType last,
|
||||
SAX* sax,
|
||||
input_format_t format = input_format_t::json,
|
||||
const bool strict = true,
|
||||
@@ -23,10 +23,11 @@ static bool sax_parse(IteratorType first, IteratorType last,
|
||||
Read from input and generate SAX events
|
||||
|
||||
1. Read from a compatible input.
|
||||
2. Read from a pair of character iterators
|
||||
2. Read from a pair of character iterators, or an iterator and a sentinel of a different type (C++20 ranges support)
|
||||
|
||||
The value_type of the iterator must be an integral type with a size of 1, 2, or 4 bytes, which will be interpreted
|
||||
respectively as UTF-8, UTF-16, and UTF-32.
|
||||
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
|
||||
the iterator type with `operator!=`.
|
||||
|
||||
The SAX event lister must follow the interface of [`json_sax`](../json_sax/index.md).
|
||||
|
||||
@@ -39,13 +40,16 @@ The SAX event lister must follow the interface of [`json_sax`](../json_sax/index
|
||||
- a `FILE` pointer
|
||||
- a C-style array of characters
|
||||
- a pointer to a null-terminated string of single byte characters
|
||||
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of
|
||||
iterators.
|
||||
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
||||
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type for overload (2); a pair of character iterators whose `value_type` is an integral type
|
||||
with a size of 1, 2, or 4 bytes (interpreted respectively as UTF-8, UTF-16, and UTF-32)
|
||||
|
||||
`SentinelType`
|
||||
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for overload (2)
|
||||
|
||||
`SAX`
|
||||
: a class fulfilling the SAX event listener interface; see [`json_sax`](../json_sax/index.md)
|
||||
|
||||
@@ -76,7 +80,7 @@ The SAX event lister must follow the interface of [`json_sax`](../json_sax/index
|
||||
: iterator to the start of a character range
|
||||
|
||||
`last` (in)
|
||||
: iterator to the end of a character range
|
||||
: iterator to the end of a character range, or a sentinel value that compares equal to the end iterator with `operator!=`
|
||||
|
||||
## Return value
|
||||
|
||||
@@ -126,7 +130,9 @@ A UTF-8 byte order mark is silently ignored.
|
||||
|
||||
- Added in version 3.2.0.
|
||||
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
||||
- Added `ignore_trailing_commas` in version 3.12.x.
|
||||
- Added `ignore_trailing_commas` in version 3.13.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ provides `<format>`, controlled by the [`JSON_HAS_STD_FORMAT`](../macros/json_ha
|
||||
- [dump](dump.md) - serialization
|
||||
- [operator<<(std::ostream&)](../operator_ltlt.md) - serialize to stream
|
||||
- [format_as](format_as.md) - customization point used by `fmt::format` (fmtlib)
|
||||
- [Serialization](../../features/serialization.md) - the serialization article
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.x.
|
||||
- Added in version 3.13.0.
|
||||
|
||||
@@ -18,6 +18,11 @@ JSON class into byte-sized characters during deserialization.
|
||||
: the container to store strings (e.g., `std::string`). Note this container is used for keys/names in objects, see
|
||||
[object_t](object_t.md).
|
||||
|
||||
`StringType` must have a `char`-compatible `value_type`: the library relies on UTF-8/`char`-based storage and
|
||||
processing internally, so `std::wstring`, `std::u16string`, and `std::u32string` are **not** valid choices for
|
||||
`StringType`. To work with wide-character data, convert it to/from UTF-8 at the boundary instead -- see the
|
||||
FAQ's [wide string handling](../../home/faq.md#wide-string-handling) section for a conversion recipe.
|
||||
|
||||
## Notes
|
||||
|
||||
#### Default type
|
||||
@@ -45,6 +50,15 @@ This implementation is interoperable as it does compare strings code unit by cod
|
||||
String values are stored as pointers in a `basic_json` type. That is, for any access to string values, a pointer of type
|
||||
`string_t*` must be dereferenced.
|
||||
|
||||
#### Cross-`basic_json` conversion requirements
|
||||
|
||||
When converting a string value from one `basic_json` specialization to another via the
|
||||
[converting constructor](basic_json.md#overload-4), the target `string_t` must be directly
|
||||
constructible from the source `basic_json`'s `string_t` type. If this requirement is not met, the
|
||||
conversion does not fail; instead, the string is silently converted as an array of character codes,
|
||||
which is incorrect. See [issue #3425](https://github.com/nlohmann/json/issues/3425) for details
|
||||
and an example.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -59,6 +59,7 @@ std::string to_string(const BasicJsonType& j)
|
||||
## See also
|
||||
|
||||
- [dump](dump.md)
|
||||
- [Serialization](../../features/serialization.md) - the serialization article
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ a string representation of the type ([`value_t`](value_t.md)):
|
||||
| array | `"array"` |
|
||||
| binary | `"binary"` |
|
||||
| discarded | `"discarded"` |
|
||||
| invalid (corrupted value) | `"invalid"` |
|
||||
|
||||
!!! note "The \"invalid\" type"
|
||||
|
||||
The `"invalid"` return value indicates a corrupted JSON value — this can occur if an enum value falls outside the
|
||||
range of valid `value_t` values. This is useful for diagnosing data corruption or internal errors.
|
||||
|
||||
## Exception safety
|
||||
|
||||
@@ -52,3 +58,4 @@ Constant.
|
||||
- Part of the public API version since 2.1.0.
|
||||
- Changed return value to `const char*` and added `noexcept` in version 3.0.0.
|
||||
- Added support for binary type in version 3.8.0.
|
||||
- Added `"invalid"` return value for corrupted JSON values in version 3.13.0.
|
||||
|
||||
@@ -149,6 +149,7 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
||||
|
||||
- [insert](insert.md) add values to an array/object
|
||||
- [merge_patch](merge_patch.md) applies a JSON Merge Patch
|
||||
- [Modifying values](../../features/modifying_values.md) - the article on modifying values
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ ValueType value(const json_pointer& ptr,
|
||||
const ValueType& default_value) const;
|
||||
```
|
||||
|
||||
This is equivalent to Python's `dict.get(key, default)`.
|
||||
|
||||
1. Returns either a copy of an object's element at the specified key `key` or a given default value if no element with
|
||||
key `key` exists.
|
||||
|
||||
@@ -184,4 +186,6 @@ changes to any JSON value.
|
||||
|
||||
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0.
|
||||
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2.
|
||||
3. Added in version 2.0.2. Extended to work with arrays in version 3.12.x.
|
||||
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0, including fixing an issue where resolving
|
||||
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
|
||||
`default_value`, as documented).
|
||||
|
||||
@@ -36,4 +36,4 @@ Constant.
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.x.
|
||||
- Added in version 3.13.0.
|
||||
|
||||
@@ -32,4 +32,4 @@ Linear in the number of reference tokens in the `json_pointer`.
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.x.
|
||||
- Added in version 3.13.0.
|
||||
|
||||
@@ -35,4 +35,4 @@ Linear in the number of reference tokens in the `json_pointer`.
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.x.
|
||||
- Added in version 3.13.0.
|
||||
|
||||
@@ -92,4 +92,4 @@ The default value is `0` (disabled — existing behavior is preserved).
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.x.
|
||||
- Added in version 3.13.0.
|
||||
|
||||
@@ -44,4 +44,4 @@ The default value is detected based on preprocessor macros such as `#!cpp __cplu
|
||||
|
||||
- Added in version 3.10.5.
|
||||
- Added `JSON_HAS_CPP_23` in version 3.12.0.
|
||||
- Added `JSON_HAS_CPP_26` in version 3.12.x.
|
||||
- Added `JSON_HAS_CPP_26` in version 3.13.0.
|
||||
|
||||
@@ -19,6 +19,20 @@ The default value is detected based on the preprocessor macros `#!cpp __cpp_lib_
|
||||
`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include(<filesystem>)`, or
|
||||
`#!cpp __has_include(<experimental/filesystem>)`.
|
||||
|
||||
!!! info "Known compiler/stdlib exclusions"
|
||||
|
||||
Even when the feature-test macro indicates filesystem support is available, the library disables it on the following broken toolchains:
|
||||
|
||||
- **MinGW + GCC 8** — disabled entirely (broken `std::filesystem` implementation; [MinGW-w64 bug 737](https://sourceforge.net/p/mingw-w64/bugs/737/))
|
||||
- **GCC (non-Clang) < 8** — disabled (no filesystem support)
|
||||
- **Clang < 7** — disabled (no filesystem support)
|
||||
- **MSVC < 19.14** — disabled (no filesystem support)
|
||||
- **iOS < 13** — disabled (no filesystem support)
|
||||
- **macOS < Catalina (10.15)** — disabled (no filesystem support)
|
||||
|
||||
If `JSON_HAS_FILESYSTEM` or `JSON_HAS_EXPERIMENTAL_FILESYSTEM` is `0` despite `__cpp_lib_filesystem` being defined, one
|
||||
of the exclusions above likely applies to your toolchain.
|
||||
|
||||
## Notes
|
||||
|
||||
- Note that older compilers or older versions of libstdc++ also require the library `stdc++fs` to be linked to for
|
||||
|
||||
@@ -13,6 +13,20 @@ The default value is detected based on the preprocessor macro `#!cpp __cpp_lib_r
|
||||
|
||||
When the macro is not defined, the library will define it to its default value.
|
||||
|
||||
!!! info "Known compiler/stdlib exclusions"
|
||||
|
||||
Even when the feature-test macro `__cpp_lib_ranges` indicates ranges support is available, the library disables it on
|
||||
the following incomplete or broken toolchains:
|
||||
|
||||
- **GCC 11.1.0** — disabled (the shipped `<ranges>` header has a syntax error; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||
- **libstdc++ < 11** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||
- **Clang < 16 with libstdc++** — disabled (incomplete ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||
- **libc++ < 160000** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||
- **nvcc (CUDA) 12.0.x and 12.1.x** — disabled (the `enable_borrowed_range` variable-template syntax triggers a parse error
|
||||
under these two toolkit versions; fixed in CUDA 12.2; [issue #3907](https://github.com/nlohmann/json/issues/3907))
|
||||
|
||||
If `JSON_HAS_RANGES` is `0` despite `__cpp_lib_ranges` being defined, one of the exclusions above likely applies to your toolchain.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -38,4 +38,4 @@ When the macro is not defined, the library will define it to its default value.
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.x.
|
||||
- Added in version 3.13.0.
|
||||
|
||||
@@ -57,7 +57,8 @@ Summary:
|
||||
: name of the base type (class, struct) `type` is derived from
|
||||
|
||||
`member` (in)
|
||||
: name of the member variable to serialize/deserialize; up to 63 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, which may also be empty
|
||||
|
||||
## Default definition
|
||||
|
||||
@@ -127,6 +128,20 @@ void to_json(BasicJsonType& j, const B& b) {
|
||||
- Macros 4, 5, and 6 have the same prerequisites of [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE](nlohmann_define_type_non_intrusive.md).
|
||||
- Serialization/deserialization of base types must be defined.
|
||||
|
||||
!!! info "Derived types without own members"
|
||||
|
||||
The member list may be empty. The macro then generates a `to_json`/`from_json` pair that only delegates to
|
||||
the base type, so `type` serializes exactly like `base_type`:
|
||||
|
||||
```cpp
|
||||
struct derived : base
|
||||
{
|
||||
NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(derived, base)
|
||||
};
|
||||
```
|
||||
|
||||
The `WITH_NAMES` variants do not support this.
|
||||
|
||||
!!! warning "Implementation limits"
|
||||
|
||||
See Implementation limits for [NLOHMANN_DEFINE_TYPE_INTRUSIVE](nlohmann_define_type_intrusive.md) and
|
||||
|
||||
@@ -33,7 +33,8 @@ Summary:
|
||||
: name of the type (class, struct) to serialize/deserialize
|
||||
|
||||
`member` (in)
|
||||
: name of the member variable to serialize/deserialize; up to 63 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, which may also be empty
|
||||
|
||||
## Default definition
|
||||
|
||||
@@ -58,10 +59,27 @@ See the examples below for the concrete generated code.
|
||||
|
||||
[GetNonDefNonCopy]: ../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
|
||||
|
||||
!!! info "Types without members"
|
||||
|
||||
The member list may be empty. The macro then generates a `to_json` that produces an empty JSON object
|
||||
`#!json {}`, and a `from_json` that reads no members:
|
||||
|
||||
```cpp
|
||||
struct marker
|
||||
{
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(marker)
|
||||
};
|
||||
```
|
||||
|
||||
The `WITH_NAMES` variants do not support this.
|
||||
|
||||
!!! warning "Implementation limits"
|
||||
|
||||
- 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.
|
||||
- These macros always produce object-style (named-key) JSON, one key per member. There is no macro variant
|
||||
that serializes a struct's members positionally into a JSON array; for that, write `to_json`/`from_json` by
|
||||
hand, building/reading a `json::array()` of the members in order.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ Summary:
|
||||
: name of the type (class, struct) to serialize/deserialize
|
||||
|
||||
`member` (in)
|
||||
: name of the (public) member variable to serialize/deserialize; up to 63 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, which may also be empty
|
||||
|
||||
## Default definition
|
||||
|
||||
@@ -59,10 +60,25 @@ See the examples below for the concrete generated code.
|
||||
|
||||
[GetNonDefNonCopy]: ../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
|
||||
|
||||
!!! info "Types without members"
|
||||
|
||||
The member list may be empty. The macro then generates a `to_json` that produces an empty JSON object
|
||||
`#!json {}`, and a `from_json` that reads no members:
|
||||
|
||||
```cpp
|
||||
struct marker {};
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(marker)
|
||||
```
|
||||
|
||||
The `WITH_NAMES` variants do not support this.
|
||||
|
||||
!!! warning "Implementation limits"
|
||||
|
||||
- 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.
|
||||
- These macros always produce object-style (named-key) JSON, one key per member. There is no macro variant
|
||||
that serializes a struct's members positionally into a JSON array; for that, write `to_json`/`from_json` by
|
||||
hand, building/reading a `json::array()` of the members in order.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -75,4 +75,4 @@ For further information please refer to the corresponding macros without `WITH_N
|
||||
|
||||
## Version history
|
||||
|
||||
1. Added in version 3.12.x.
|
||||
1. Added in version 3.13.0.
|
||||
|
||||
@@ -102,4 +102,4 @@ inline void from_json(const BasicJsonType& j, type& e);
|
||||
|
||||
## Version history
|
||||
|
||||
Added in version 3.12.x.
|
||||
Added in version 3.13.0.
|
||||
|
||||
@@ -33,6 +33,18 @@ A UTF-8 byte order mark is silently ignored.
|
||||
Invalid Unicode escapes and unpaired surrogates in the input are reported as
|
||||
[`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) with a detailed message.
|
||||
|
||||
`operator>>` parses exactly one JSON value and leaves the stream positioned right after it, so it can be called
|
||||
repeatedly to read a sequence of concatenated JSON values from the same stream:
|
||||
|
||||
```cpp
|
||||
json j1, j2;
|
||||
input >> j1; // parses the first value, stream now positioned right after it
|
||||
input >> j2; // parses the next value
|
||||
```
|
||||
|
||||
Note this does **not** work for [JSON Lines](../features/parsing/json_lines.md) (newline-delimited JSON) input --
|
||||
see that page for why and for the recommended alternative.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
This function replaces function `#!cpp std::istream& operator<<(basic_json& j, std::istream& i)` which has
|
||||
|
||||
@@ -56,8 +56,12 @@ Linear.
|
||||
--8<-- "examples/operator_literal_json.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 1.0.0.
|
||||
- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0.
|
||||
- Added `char8_t*` overload in 3.12.x.
|
||||
- Added `char8_t*` overload in 3.13.0.
|
||||
|
||||
@@ -63,4 +63,4 @@ Linear.
|
||||
|
||||
- Added in version 2.0.0.
|
||||
- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0.
|
||||
- Added `char8_t*` overload in 3.12.x.
|
||||
- Added `char8_t*` overload in 3.13.0.
|
||||
|
||||
@@ -80,6 +80,12 @@ Linear.
|
||||
```json
|
||||
--8<-- "examples/operator_ltlt__json_pointer.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [dump](basic_json/dump.md) - serialize to a JSON-formatted string
|
||||
- [Serialization](../features/serialization.md) - the serialization article
|
||||
|
||||
## Version history
|
||||
|
||||
1. Added in version 1.0.0. Added support for indentation character and deprecated
|
||||
|
||||
@@ -10,6 +10,10 @@ violations will result in a failed build.
|
||||
|
||||
Any compiler with complete C++11 support can compile the library without warnings.
|
||||
|
||||
Note: C++20 modules support may hit compiler-specific issues not covered by the general compiler matrix below. See [Modules](../features/modules.md#known-issues) for known issues and workarounds.
|
||||
|
||||
Note: Some modern features (like C++20 ranges or filesystem support) may be disabled on specific broken or incomplete toolchains even when standard feature-test macros indicate support. See [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md) and [`JSON_HAS_FILESYSTEM`](../api/macros/json_has_filesystem.md) for details on known exclusions.
|
||||
|
||||
- [x] The library is compiled with 50+ different C++ compilers with different operating systems and platforms,
|
||||
including the oldest versions known to compile the library.
|
||||
|
||||
@@ -62,12 +66,14 @@ violations will result in a failed build.
|
||||
| Clang 20.1.1 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| Clang 20.1.8 with GNU-like command-line | x86_64 | Windows Server 2022 (Build 20348) | GitHub |
|
||||
| Clang 21.1.8 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| CUDA 11.0.221 (nvcc) | x86_64 | Ubuntu 20.04 LTS | GitHub |
|
||||
| CUDA 11.8.0 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||
| CUDA 12.1.1 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||
| CUDA 12.6.3 (nvcc) | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||
| Emscripten 4.0.6 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 4.8.5 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 4.9.3 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 5.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 6.4.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 4.8.5 | x86_64 | Ubuntu 20.04 LTS | GitHub |
|
||||
| GNU 4.9.3 | x86_64 | Ubuntu 20.04 LTS | GitHub |
|
||||
| GNU 5.5.0 | x86_64 | Ubuntu 20.04 LTS | GitHub |
|
||||
| GNU 6.4.0 | x86_64 | Ubuntu 20.04 LTS | GitHub |
|
||||
| GNU 7.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 8.5.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 9.3.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
@@ -84,7 +90,7 @@ violations will result in a failed build.
|
||||
| GNU 15.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 16.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 16.1.0 | arm64 | Linux 6.1.100 | Cirrus CI |
|
||||
| icpc (ICC) 2021.5.0 20211109 | x86_64 | Ubuntu 20.04.3 LTS | GitHub |
|
||||
| icpc (ICC) 2021.10.0 20230609 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||
| icpx (Intel oneAPI DPC++/C++) 2025.3.2 | x86_64 | Ubuntu 24.04 LTS | GitHub |
|
||||
| nvc++ (NVIDIA HPC SDK) 25.5-0 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||
| MSVC 19.0.24241.7 | x86 | Windows 8.1 | AppVeyor |
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
json parse_strict(const std::string& input)
|
||||
{
|
||||
// one key set per nesting depth, reused across sibling objects
|
||||
std::vector<std::unordered_set<std::string>> keys;
|
||||
|
||||
auto reject_duplicate_keys = [&](int depth, json::parse_event_t event, json & parsed)
|
||||
{
|
||||
if (event == json::parse_event_t::object_start)
|
||||
{
|
||||
// keys of this object are reported at depth+1 (see the event table above)
|
||||
const auto child_depth = static_cast<std::size_t>(depth) + 1;
|
||||
if (keys.size() <= child_depth)
|
||||
{
|
||||
keys.resize(child_depth + 1);
|
||||
}
|
||||
keys[child_depth].clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event == json::parse_event_t::key)
|
||||
{
|
||||
auto& seen = keys[static_cast<std::size_t>(depth)];
|
||||
const auto& key = parsed.get_ref<const std::string&>();
|
||||
if (!seen.insert(key).second)
|
||||
{
|
||||
throw std::runtime_error("duplicate JSON object key: " + key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return json::parse(input, reject_duplicate_keys);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// parsing succeeds when all keys are unique
|
||||
json j = parse_strict(R"({"one": 1, "two": 2})");
|
||||
std::cout << j << '\n';
|
||||
|
||||
// parsing throws when a key is repeated
|
||||
try
|
||||
{
|
||||
parse_strict(R"({"one": 1, "one": 2})");
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
{"one":1,"two":2}
|
||||
duplicate JSON object key: one
|
||||
@@ -85,7 +85,7 @@ 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 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:
|
||||
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 choose the macro based on the needed features:
|
||||
|
||||
- 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`.
|
||||
@@ -139,7 +139,7 @@ For _derived_ classes and structs, use the following macros
|
||||
```cpp
|
||||
namespace ns {
|
||||
struct person_derived : person {
|
||||
std:string email;
|
||||
std::string email;
|
||||
};
|
||||
|
||||
NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(person_derived, person, email)
|
||||
@@ -180,6 +180,67 @@ For _derived_ classes and structs, use the following macros
|
||||
}
|
||||
```
|
||||
|
||||
!!! warning "Overriding conversions for natively-supported types"
|
||||
|
||||
The library already provides built-in `to_json`/`from_json` conversions for STL containers such as
|
||||
`std::vector`, `std::array`, and `std::map`. Defining your own free-function `to_json`/`from_json` overload
|
||||
for one of these container types directly (instead of for your own type) can conflict with the built-in
|
||||
overload during overload resolution, producing compiler errors ("no matching overloaded function",
|
||||
"call is ambiguous") that vary by compiler and library version. If you need different conversion behavior
|
||||
for a container type the library already handles, wrap it in your own type (or use `adl_serializer`
|
||||
specialization, as shown [above](#how-do-i-convert-third-party-types) for `boost::optional`) instead of
|
||||
trying to re-specialize `to_json`/`from_json` for the container type itself.
|
||||
|
||||
!!! warning "Raw C-style arrays"
|
||||
|
||||
Members declared as raw C-style arrays (e.g., `char buf[1024]`) do not round-trip safely through
|
||||
`NLOHMANN_DEFINE_TYPE_*` macros or the default (de)serializers: `to_json` serializes any `char` array as a
|
||||
JSON *string* (matching the `std::string`-constructible overload), but the `from_json` overload for
|
||||
fixed-size arrays expects a JSON *array* and iterates it element-wise, which fails with a `type_error` when
|
||||
given a string. Use `std::string`, `std::array<char, N>`, or a manually written `to_json`/`from_json` pair
|
||||
for such members instead.
|
||||
|
||||
!!! note "Macros and `nlohmann::ordered_json`"
|
||||
|
||||
The `NLOHMANN_DEFINE_TYPE_*`/`NLOHMANN_DEFINE_DERIVED_TYPE_*` macros are generic over any `basic_json`
|
||||
specialization, including `nlohmann::ordered_json`. Simply use `ordered_json` as the target type and members
|
||||
are serialized in declaration order -- no separate macro or extra code is needed.
|
||||
|
||||
```cpp
|
||||
namespace ns {
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
|
||||
}
|
||||
|
||||
ns::person p{"Ned Flanders", "744 Evergreen Terrace", 60};
|
||||
nlohmann::ordered_json j = p; // keys appear in declaration order: name, address, age
|
||||
```
|
||||
|
||||
!!! note "Zero-member types"
|
||||
|
||||
All 12 `NLOHMANN_DEFINE_TYPE_*`/`NLOHMANN_DEFINE_DERIVED_TYPE_*` macros (excluding the `WITH_NAMES` variants)
|
||||
also accept types with no member variables to serialize, producing/accepting an empty JSON object `{}`
|
||||
(or, for the derived-type macros, just the base class's own JSON representation):
|
||||
|
||||
```cpp
|
||||
namespace ns {
|
||||
struct marker {
|
||||
bool operator==(const marker&) const { return true; }
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(marker)
|
||||
};
|
||||
}
|
||||
|
||||
ns::marker m{};
|
||||
nlohmann::json j = m; // {}
|
||||
```
|
||||
|
||||
!!! note "No macro for non-default-constructible types"
|
||||
|
||||
There is currently no `NLOHMANN_DEFINE_TYPE_*`-style macro for types that are not
|
||||
[DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). This is not an
|
||||
intentional omission of documentation -- no such macro exists yet; see
|
||||
[How can I use `get()` for non-default constructible/non-copyable types?](#how-can-i-use-get-for-non-default-constructiblenon-copyable-types)
|
||||
for the manual pattern to use instead.
|
||||
|
||||
## How do I convert third-party types?
|
||||
|
||||
This requires a bit more advanced technique. But first, let us see how this conversion mechanism works:
|
||||
@@ -270,6 +331,49 @@ namespace nlohmann {
|
||||
}
|
||||
```
|
||||
|
||||
## Why can't I convert to/from `std::any`?
|
||||
|
||||
`std::any` is intentionally excluded from `get<T>()`/generic conversion support, so `get<std::any>()` and
|
||||
containers like `std::map<std::string, std::any>` fail to compile by design -- there is no way to know, from a
|
||||
`json` value alone, which concrete type to store inside the `std::any`. To work with heterogeneous JSON values,
|
||||
dispatch on the value's type manually and construct the `std::any` (or extract from it) yourself:
|
||||
|
||||
```cpp
|
||||
std::any value_to_any(const json& j) {
|
||||
if (j.is_boolean()) { return j.get<bool>(); }
|
||||
if (j.is_number_integer()) { return j.get<int>(); }
|
||||
if (j.is_number_float()) { return j.get<double>(); }
|
||||
if (j.is_string()) { return j.get<std::string>(); }
|
||||
// ... handle other types (arrays, objects) as needed for your use case
|
||||
return {};
|
||||
}
|
||||
|
||||
json any_to_json(const std::any& a) {
|
||||
if (a.type() == typeid(bool)) { return std::any_cast<bool>(a); }
|
||||
if (a.type() == typeid(int)) { return std::any_cast<int>(a); }
|
||||
if (a.type() == typeid(double)) { return std::any_cast<double>(a); }
|
||||
if (a.type() == typeid(std::string)) { return std::any_cast<std::string>(a); }
|
||||
return nullptr;
|
||||
}
|
||||
```
|
||||
|
||||
## Why does serializing a `std::map`/`std::unordered_map` with non-string keys produce an array?
|
||||
|
||||
A `std::map`/`std::unordered_map` whose key type is not string-like (e.g., `std::map<int, std::string>`) is
|
||||
serialized as a JSON *array* of 2-element `[key, value]` arrays, not as a JSON object -- JSON object keys must be
|
||||
strings, so the library cannot represent an integer-keyed map as an object.
|
||||
|
||||
```cpp
|
||||
std::map<int, std::string> m{{1, "one"}, {2, "two"}};
|
||||
json j = m;
|
||||
// j is [[1,"one"],[2,"two"]], not {"1":"one","2":"two"}
|
||||
```
|
||||
|
||||
## Why does `std::wstring` convert or dump incorrectly?
|
||||
|
||||
The library assumes UTF-8 encoding internally, so `std::wstring` is not supported out of the box -- see the FAQ
|
||||
entry on [wide string handling](../home/faq.md#wide-string-handling) for why, and for a UTF-8 conversion recipe.
|
||||
|
||||
## Can I write my own serializer? (Advanced use)
|
||||
|
||||
Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-udt.cpp) in the test suite, to see a few examples.
|
||||
|
||||
@@ -11,7 +11,7 @@ Runtime assertions can be switched off by defining the preprocessor macro `NDEBU
|
||||
|
||||
## Change assertion behavior
|
||||
|
||||
The behavior of runtime assertions can be changes by defining macro [`JSON_ASSERT(x)`](../api/macros/json_assert.md)
|
||||
The behavior of runtime assertions can be changed by defining macro [`JSON_ASSERT(x)`](../api/macros/json_assert.md)
|
||||
before including the `json.hpp` header.
|
||||
|
||||
## Function with runtime assertions
|
||||
|
||||
@@ -123,7 +123,7 @@ The library uses the following mapping from JSON values types to BJData types ac
|
||||
The current version of this library does not yet support automatic detection of and conversion from a nested JSON
|
||||
array input to a BJData ND-array.
|
||||
|
||||
[JDataAAFmt]: https://github.com/NeuroJSON/jdata/blob/master/JData_specification.md#annotated-storage-of-n-d-arrays)
|
||||
[JDataAAFmt]: https://github.com/NeuroJSON/jdata/blob/master/JData_specification.md#annotated-storage-of-n-d-arrays
|
||||
|
||||
!!! info "Restrictions in optimized data types for arrays and objects"
|
||||
|
||||
@@ -146,7 +146,7 @@ The library uses the following mapping from JSON values types to BJData types ac
|
||||
suggested by the BJData documentation. In particular, this means that the serialization and the deserialization of
|
||||
JSON containing binary values into BJData and back will result in a different JSON object.
|
||||
|
||||
[BJDataBinArr]: https://github.com/NeuroJSON/bjdata/blob/master/Binary_JData_Specification.md#optimized-binary-array)
|
||||
[BJDataBinArr]: https://github.com/NeuroJSON/bjdata/blob/master/Binary_JData_Specification.md#optimized-binary-array
|
||||
|
||||
??? example
|
||||
|
||||
|
||||
@@ -52,28 +52,29 @@ The library uses the following mapping from JSON values types to BSON types:
|
||||
|
||||
The library maps BSON record types to JSON value types as follows:
|
||||
|
||||
| BSON type | BSON marker byte | JSON value type |
|
||||
|-----------------------|------------------|-----------------|
|
||||
| double | 0x01 | number_float |
|
||||
| string | 0x02 | string |
|
||||
| document | 0x03 | object |
|
||||
| array | 0x04 | array |
|
||||
| binary | 0x05 | binary |
|
||||
| undefined | 0x06 | *unsupported* |
|
||||
| ObjectId | 0x07 | *unsupported* |
|
||||
| boolean | 0x08 | boolean |
|
||||
| UTC Date-Time | 0x09 | *unsupported* |
|
||||
| null | 0x0A | null |
|
||||
| Regular Expr. | 0x0B | *unsupported* |
|
||||
| DB Pointer | 0x0C | *unsupported* |
|
||||
| JavaScript Code | 0x0D | *unsupported* |
|
||||
| Symbol | 0x0E | *unsupported* |
|
||||
| JavaScript Code | 0x0F | *unsupported* |
|
||||
| int32 | 0x10 | number_integer |
|
||||
| uint64(Timestamp) | 0x11 | number_unsigned |
|
||||
| 128-bit decimal float | 0x13 | *unsupported* |
|
||||
| Max Key | 0x7F | *unsupported* |
|
||||
| Min Key | 0xFF | *unsupported* |
|
||||
| BSON type | BSON marker byte | JSON value type |
|
||||
|--------------------------|------------------|-----------------|
|
||||
| double | 0x01 | number_float |
|
||||
| string | 0x02 | string |
|
||||
| document | 0x03 | object |
|
||||
| array | 0x04 | array |
|
||||
| binary | 0x05 | binary |
|
||||
| undefined | 0x06 | *unsupported* |
|
||||
| ObjectId | 0x07 | *unsupported* |
|
||||
| boolean | 0x08 | boolean |
|
||||
| UTC Date-Time | 0x09 | *unsupported* |
|
||||
| null | 0x0A | null |
|
||||
| Regular Expr. | 0x0B | *unsupported* |
|
||||
| DB Pointer | 0x0C | *unsupported* |
|
||||
| JavaScript Code | 0x0D | *unsupported* |
|
||||
| Symbol | 0x0E | *unsupported* |
|
||||
| JavaScript Code w/ scope | 0x0F | *unsupported* |
|
||||
| int32 | 0x10 | number_integer |
|
||||
| uint64(Timestamp) | 0x11 | number_unsigned |
|
||||
| int64 | 0x12 | number_integer |
|
||||
| 128-bit decimal float | 0x13 | *unsupported* |
|
||||
| Max Key | 0x7F | *unsupported* |
|
||||
| Min Key | 0xFF | *unsupported* |
|
||||
|
||||
!!! warning "Incomplete mapping"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ extremely small code sizes, fairly small message size, and extensibility without
|
||||
|
||||
!!! abstract "References"
|
||||
|
||||
- [CBOR Website](http://cbor.io) - the main source on CBOR
|
||||
- [CBOR Website](http://cbor.io) - the main source on CBOR
|
||||
- [CBOR Playground](http://cbor.me) - an interactive webpage to translate between JSON and CBOR
|
||||
- [RFC 7049](https://tools.ietf.org/html/rfc7049) - the CBOR specification
|
||||
|
||||
@@ -37,22 +37,22 @@ The library uses the following mapping from JSON values types to CBOR types acco
|
||||
| number_float | *any value representable by a float* | Single-Precision Float | 0xFA |
|
||||
| number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB |
|
||||
| string | *length*: 0..23 | UTF-8 string | 0x60..0x77 |
|
||||
| string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 |
|
||||
| string | *length*: 24..255 | UTF-8 string (1 byte follow) | 0x78 |
|
||||
| string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 |
|
||||
| string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A |
|
||||
| string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B |
|
||||
| array | *size*: 0..23 | array | 0x80..0x97 |
|
||||
| array | *size*: 23..255 | array (1 byte follow) | 0x98 |
|
||||
| array | *size*: 24..255 | array (1 byte follow) | 0x98 |
|
||||
| array | *size*: 256..65535 | array (2 bytes follow) | 0x99 |
|
||||
| array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A |
|
||||
| array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B |
|
||||
| object | *size*: 0..23 | map | 0xA0..0xB7 |
|
||||
| object | *size*: 23..255 | map (1 byte follow) | 0xB8 |
|
||||
| object | *size*: 24..255 | map (1 byte follow) | 0xB8 |
|
||||
| object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 |
|
||||
| object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA |
|
||||
| object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB |
|
||||
| binary | *size*: 0..23 | byte string | 0x40..0x57 |
|
||||
| binary | *size*: 23..255 | byte string (1 byte follow) | 0x58 |
|
||||
| binary | *size*: 24..255 | byte string (1 byte follow) | 0x58 |
|
||||
| binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 |
|
||||
| binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A |
|
||||
| binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B |
|
||||
@@ -66,7 +66,15 @@ see "binary" cells in the table above.
|
||||
|
||||
!!! info "NaN/infinity handling"
|
||||
|
||||
If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the normal JSON serialization which serializes NaN or Infinity to `null`.
|
||||
`NaN`, `Infinity`, and `-Infinity` are serialized as a CBOR half-precision float (type 0xF9, 3 bytes total):
|
||||
`NaN` as `0xF9 0x7E 0x00`, `Infinity` as `0xF9 0x7C 0x00`, and `-Infinity` as `0xF9 0xFC 0x00`. This behavior
|
||||
differs from the normal JSON serialization which serializes NaN or Infinity to `null`.
|
||||
|
||||
!!! note
|
||||
|
||||
Prior to version 3.13.0, NaN and Infinity were instead serialized as a CBOR double-precision float (type 0xFB,
|
||||
9 bytes total), because the check used to select a smaller encoding compared magnitudes with NaN, which is
|
||||
always `false` and caused the intended half-precision path to be skipped.
|
||||
|
||||
!!! info "Unused CBOR types"
|
||||
|
||||
@@ -160,6 +168,13 @@ The library maps CBOR types to JSON value types as follows:
|
||||
- simple values (0xE0..0xF3, 0xF8)
|
||||
- undefined (0xF7)
|
||||
|
||||
!!! warning "Negative integer overflow"
|
||||
|
||||
CBOR negative integers (major type 1) are decoded as `-1 - n`. If the encoded magnitude `n` is too large for the
|
||||
result to fit into `number_integer_t` (`std::int64_t` by default), parsing fails with a
|
||||
[`parse_error.112`](../../home/exceptions.md#jsonexceptionparse_error112) exception rather than overflowing
|
||||
silently.
|
||||
|
||||
!!! warning "Object keys"
|
||||
|
||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
||||
|
||||
@@ -41,7 +41,7 @@ See [binary values](../binary_values.md) for more information.
|
||||
|--------------------|-------------|--------------|-------------------|---------------|
|
||||
| BJData | 53.2 % | 91.1 % | 78.1 % | 96.6 % |
|
||||
| BJData (size) | 58.6 % | 92.1 % | 86.7 % | 97.4 % |
|
||||
| BJData (size+tyoe) | 58.6 % | 92.1 % | 86.5 % | 97.4 % |
|
||||
| BJData (size+type) | 58.6 % | 92.1 % | 86.5 % | 97.4 % |
|
||||
| BSON | 85.8 % | 95.2 % | 95.8 % | 106.7 % |
|
||||
| CBOR | 50.5 % | 86.3 % | 68.4 % | 88.0 % |
|
||||
| MessagePack | 50.5 % | 86.0 % | 68.5 % | 87.9 % |
|
||||
|
||||
@@ -67,8 +67,15 @@ specification:
|
||||
|
||||
!!! info "NaN/infinity handling"
|
||||
|
||||
If NaN or Infinity are stored inside a JSON number, they are serialized properly in contrast to the
|
||||
[dump](../../api/basic_json/dump.md) function which serializes NaN or Infinity to `null`.
|
||||
`NaN`, `Infinity`, and `-Infinity` are serialized as a MessagePack float 32 (type 0xCA, 5 bytes total),
|
||||
regardless of magnitude, in contrast to the [dump](../../api/basic_json/dump.md) function which serializes NaN
|
||||
or Infinity to `null`.
|
||||
|
||||
!!! note
|
||||
|
||||
Prior to version 3.13.0, NaN and Infinity were instead serialized as a MessagePack float 64 (type 0xCB, 9 bytes
|
||||
total), because the check used to select the smaller float 32 encoding compared magnitudes with NaN, which is
|
||||
always `false` and caused the float 32 path to be skipped.
|
||||
|
||||
??? example
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ binary.has_subtype(); // returns false
|
||||
binary_with_subtype.has_subtype(); // returns true
|
||||
|
||||
binary_with_subtype.clear_subtype();
|
||||
binary_with_subtype.has_subtype(); // returns true
|
||||
binary_with_subtype.has_subtype(); // returns false
|
||||
|
||||
binary_with_subtype.set_subtype(42);
|
||||
binary.set_subtype(23);
|
||||
@@ -146,7 +146,7 @@ as an array of uint8 values. The library implements this translation.
|
||||
auto v = json::to_bjdata(j);
|
||||
```
|
||||
|
||||
`v` is a `std::vector<std::uint8t>` with the following 20 elements:
|
||||
`v` is a `std::vector<std::uint8_t>` with the following 20 elements:
|
||||
|
||||
```c
|
||||
0x7B // '{'
|
||||
@@ -158,10 +158,10 @@ as an array of uint8 values. The library implements this translation.
|
||||
0x7D // '}'
|
||||
```
|
||||
|
||||
The following code uses the type and size optimization for UBJSON:
|
||||
The following code uses the type and size optimization for BJData:
|
||||
|
||||
```cpp
|
||||
// convert to UBJSON using the size and type optimization
|
||||
// convert to BJData using the size and type optimization
|
||||
auto v = json::to_bjdata(j, true, true);
|
||||
```
|
||||
|
||||
@@ -178,7 +178,7 @@ as an array of uint8 values. The library implements this translation.
|
||||
0xCA 0xFE 0xBA 0xBE // content
|
||||
```
|
||||
|
||||
Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would
|
||||
Note that subtype (42) is **not** serialized and that BJData has **no binary type**, and deserializing `v` would
|
||||
yield the following value:
|
||||
|
||||
```json
|
||||
@@ -205,7 +205,7 @@ unsigned 8-bit integer. If no subtype is given, the generic binary subtype 0x00
|
||||
auto v = json::to_bson(j);
|
||||
```
|
||||
|
||||
`v` is a `std::vector<std::uint8t>` with the following 22 elements:
|
||||
`v` is a `std::vector<std::uint8_t>` with the following 22 elements:
|
||||
|
||||
```c
|
||||
0x16 0x00 0x00 0x00 // number of bytes in the document
|
||||
@@ -247,7 +247,7 @@ byte array.
|
||||
auto v = json::to_cbor(j);
|
||||
```
|
||||
|
||||
`v` is a `std::vector<std::uint8t>` with the following 15 elements:
|
||||
`v` is a `std::vector<std::uint8_t>` with the following 15 elements:
|
||||
|
||||
```c
|
||||
0xA1 // map(1)
|
||||
@@ -291,7 +291,7 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used.
|
||||
auto v = json::to_msgpack(j);
|
||||
```
|
||||
|
||||
`v` is a `std::vector<std::uint8t>` with the following 14 elements:
|
||||
`v` is a `std::vector<std::uint8_t>` with the following 14 elements:
|
||||
|
||||
```c
|
||||
0x81 // fixmap1
|
||||
@@ -331,7 +331,7 @@ as an array of uint8 values. The library implements this translation.
|
||||
auto v = json::to_ubjson(j);
|
||||
```
|
||||
|
||||
`v` is a `std::vector<std::uint8t>` with the following 20 elements:
|
||||
`v` is a `std::vector<std::uint8_t>` with the following 20 elements:
|
||||
|
||||
```c
|
||||
0x7B // '{'
|
||||
|
||||
@@ -11,7 +11,7 @@ This library does not support comments *by default*. It does so for three reason
|
||||
|
||||
3. It is dangerous for interoperability if some libraries add comment support while others do not. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
|
||||
|
||||
However, you can set parameter `ignore_comments` to `#!cpp true` in the [`parse`](../api/basic_json/parse.md) function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.
|
||||
However, you can set parameter `ignore_comments` to `#!cpp true` in the [`parse`](../api/basic_json/parse.md) function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace. Combined with `ignore_trailing_commas` (also a `parse` parameter), this covers what is commonly referred to as **JSONC** (JSON with Comments, as used e.g. by Visual Studio Code's `.jsonc` files) -- comments and trailing commas, nothing more. This is a different, smaller extension than [JSON5](https://json5.org), which additionally allows unquoted keys, single-quoted strings, and other syntax changes that this library does not support.
|
||||
|
||||
For more information, see [JSON With Commas and Comments (JWCC)](https://nigeltao.github.io/blog/2021/json-with-commas-comments.html).
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
# Converting values
|
||||
|
||||
A `basic_json` value stores JSON data, but most of the time you want to move that data into ordinary C++ types (an
|
||||
`#!cpp int`, a `#!cpp std::string`, a `#!cpp std::vector`, or one of your own structs) and back. This page describes how
|
||||
these conversions work.
|
||||
|
||||
## Getting values out
|
||||
|
||||
The [`get`](../api/basic_json/get.md) function template returns a copy of the stored value converted to the requested
|
||||
type:
|
||||
|
||||
```cpp
|
||||
json j = R"({"name": "Mary", "age": 42, "hobbies": ["hiking", "reading"]})"_json;
|
||||
|
||||
auto name = j["name"].get<std::string>(); // "Mary"
|
||||
auto age = j["age"].get<int>(); // 42
|
||||
auto hobbies = j["hobbies"].get<std::vector<std::string>>(); // {"hiking", "reading"}
|
||||
```
|
||||
|
||||
!!! note "Getting a string without quotes"
|
||||
|
||||
A frequent point of confusion: use [`get`](../api/basic_json/get.md), **not** [`dump`](serialization.md), to read a
|
||||
string value. `#!cpp j["name"].get<std::string>()` yields `#!cpp Mary`, whereas `#!cpp j["name"].dump()` yields the
|
||||
JSON text `#!cpp "Mary"` (**with** quotes), because `dump` always produces a JSON text.
|
||||
|
||||
Alternatively, [`get_to`](../api/basic_json/get_to.md) writes into an existing variable and deduces the target type,
|
||||
which avoids repeating it:
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/get_to.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/get_to.output"
|
||||
```
|
||||
|
||||
The library already knows how to convert to and from the scalar types and the STL containers (such as
|
||||
`#!cpp std::vector`, `#!cpp std::map`, `#!cpp std::array`, `#!cpp std::optional`, and many more). Converting a JSON
|
||||
object back to a `#!cpp std::map` or a JSON array back to a `#!cpp std::vector` therefore works without any extra code:
|
||||
|
||||
```cpp
|
||||
json j = {{"one", 1}, {"two", 2}};
|
||||
auto m = j.get<std::map<std::string, int>>(); // {{"one", 1}, {"two", 2}}
|
||||
```
|
||||
|
||||
## Implicit conversions
|
||||
|
||||
By default, a JSON value implicitly converts to a compatible C++ type, so the explicit `get` call can often be omitted:
|
||||
|
||||
```cpp
|
||||
json j = "Hello";
|
||||
std::string s = j; // implicit conversion, same as j.get<std::string>()
|
||||
```
|
||||
|
||||
Implicit conversions are convenient but can be surprising (for example, in overload resolution or with `auto`). They can
|
||||
be disabled by defining [`JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md) to `#!cpp 0`,
|
||||
which forces the explicit `get` form and can catch unintended conversions at compile time.
|
||||
|
||||
!!! warning "Conversions do not range-check numbers"
|
||||
|
||||
Just like C++ itself, the `get` family performs numeric conversions without range checks — retrieving a
|
||||
floating-point value as an integer truncates it, and narrowing conversions may overflow. See
|
||||
[number conversion](types/number_handling.md#number-conversion) for details and how to guard against it.
|
||||
|
||||
!!! warning "std::optional direct construction from JSON null throws"
|
||||
|
||||
Constructing or assigning `std::optional<T>` directly from a JSON value does not correctly produce
|
||||
`std::nullopt` for a JSON `null`:
|
||||
|
||||
```cpp
|
||||
json j_null;
|
||||
std::optional<std::string> opt = j_null; // ❌ throws type_error 302
|
||||
```
|
||||
|
||||
This is due to C++ language rules: `std::optional<T>` has its own converting constructor that is chosen over
|
||||
`basic_json::operator T()` when both are viable. Use `get<std::optional<T>>()` or `get_to()` instead:
|
||||
|
||||
```cpp
|
||||
auto opt = j_null.get<std::optional<std::string>>(); // ✅ std::nullopt
|
||||
j_null.get_to(opt); // ✅ std::nullopt
|
||||
```
|
||||
|
||||
!!! warning "`static_cast` and `get<std::optional<T>>()` are not guaranteed equivalent"
|
||||
|
||||
`operator ValueType()` (used by `static_cast` and implicit conversions) intentionally excludes
|
||||
`std::optional<T>` from delegating to `get<T>()`, to avoid a constructor ambiguity with
|
||||
`std::optional<T>`'s own converting constructor from `basic_json`. As a result,
|
||||
`static_cast<std::optional<T>>(json_value)` goes through `std::optional<T>`'s own converting
|
||||
constructor rather than through `get<std::optional<T>>()`, which can behave differently -- for example,
|
||||
with a custom `adl_serializer<std::optional<T>>` specialization. Prefer `get<std::optional<T>>()`/`get_to()`
|
||||
over `static_cast` for optional types.
|
||||
|
||||
!!! warning "Converting to a fixed-size `std::array` does not check length"
|
||||
|
||||
Converting a JSON array to `#!cpp std::array<T, N>` does not check that the JSON array's size matches `N`:
|
||||
if the JSON array is longer, the extra elements are silently dropped; if it is shorter, the remaining
|
||||
`std::array` elements are left default-constructed. No exception is thrown in either case.
|
||||
|
||||
```cpp
|
||||
json j = {1, 2, 3, 4, 5};
|
||||
auto a = j.get<std::array<int, 3>>(); // {1, 2, 3} -- elements 4 and 5 silently dropped
|
||||
```
|
||||
|
||||
## Omitting a field when serializing `std::optional`
|
||||
|
||||
By default, `to_json` for `std::optional<T>` writes either the value or `#!json null` -- there is no built-in way
|
||||
to make a field disappear from the serialized object entirely when the `std::optional` is `std::nullopt`. Because
|
||||
a specialization of `adl_serializer<std::optional<T>>` only controls how the *value* is converted (it cannot
|
||||
prevent the containing object's `to_json` from inserting the key in the first place), omission has to be
|
||||
implemented in the *containing* type's `to_json`:
|
||||
|
||||
```cpp
|
||||
struct person {
|
||||
std::string name;
|
||||
std::optional<int> age;
|
||||
};
|
||||
|
||||
void to_json(json& j, const person& p) {
|
||||
j = json{{"name", p.name}};
|
||||
if (p.age) {
|
||||
j["age"] = *p.age; // key is only inserted when the optional has a value
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Putting values in
|
||||
|
||||
The reverse direction works the same way: assigning or constructing a `json` from a C++ value converts it to JSON.
|
||||
|
||||
```cpp
|
||||
std::vector<int> numbers = {1, 2, 3};
|
||||
json j = numbers; // [1,2,3]
|
||||
```
|
||||
|
||||
## Your own types
|
||||
|
||||
The conversions above are built in for standard types. To make the same syntax work for **your own** types, provide
|
||||
`to_json`/`from_json` functions (or use one of the convenience macros). This is described in detail on the
|
||||
[arbitrary types conversions](arbitrary_types.md) page. Enums can be mapped to strings as described in
|
||||
[specializing enum conversion](enum_conversion.md).
|
||||
|
||||
## See also
|
||||
|
||||
- [`get`](../api/basic_json/get.md) - get a copy converted to a given type
|
||||
- [`get_to`](../api/basic_json/get_to.md) - convert into an existing variable
|
||||
- [`get_ref`](../api/basic_json/get_ref.md) / [`get_ptr`](../api/basic_json/get_ptr.md) - access the stored value without copying
|
||||
- [Arbitrary types conversions](arbitrary_types.md) - support your own types
|
||||
- [`JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md) - toggle implicit conversions
|
||||
@@ -0,0 +1,103 @@
|
||||
# Creating JSON values
|
||||
|
||||
There are several ways to create a JSON value in memory. This page gives an overview; to read a value from JSON text
|
||||
instead, see [parsing](parsing/index.md).
|
||||
|
||||
## From C++ values
|
||||
|
||||
Any value of a supported C++ type can be assigned to or used to construct a `json`:
|
||||
|
||||
```cpp
|
||||
json j_number = 42;
|
||||
json j_float = 3.141;
|
||||
json j_string = "Hello";
|
||||
json j_boolean = true;
|
||||
json j_null = nullptr;
|
||||
json j_vector = std::vector<int>{1, 2, 3}; // array
|
||||
```
|
||||
|
||||
See [converting values](conversions.md) for the full set of supported types.
|
||||
|
||||
## With initializer lists
|
||||
|
||||
Objects and arrays can be written concisely with brace-enclosed initializer lists:
|
||||
|
||||
```cpp
|
||||
// an array
|
||||
json array = {1, 2, 3, 4};
|
||||
|
||||
// an object (a list of key/value pairs)
|
||||
json object = {
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{"list", {1, 0, 2}},
|
||||
{"object", {{"currency", "USD"}, {"value", 42.99}}}
|
||||
};
|
||||
```
|
||||
|
||||
The library decides between an array and an object based on the content: a list whose elements are all two-element lists
|
||||
with a string as the first element is treated as an object, everything else as an array.
|
||||
|
||||
!!! warning "Ambiguous cases: `#!cpp {}` vs. `#!cpp []`"
|
||||
|
||||
Because the same `#!cpp {}` syntax is used for both arrays and objects, some cases are ambiguous. To force a
|
||||
particular type, use the explicit factory functions [`json::array`](../api/basic_json/array.md) and
|
||||
[`json::object`](../api/basic_json/object.md):
|
||||
|
||||
```cpp
|
||||
json empty_array_explicit = json::array(); // []
|
||||
json empty_object_explicit = json::object(); // {}
|
||||
|
||||
// a JSON array with one object, not an object with one member
|
||||
json array_of_objects = json::array({{"key", "value"}}); // [{"key":"value"}]
|
||||
```
|
||||
|
||||
Related to this, single-element brace initialization such as `#!cpp json j{value};` wraps the element in a
|
||||
single-element **array** by default, and its behavior even differs between compilers. See the
|
||||
[FAQ](../home/faq.md#brace-initialization-yields-arrays) for details and the opt-in
|
||||
[`JSON_BRACE_INIT_COPY_SEMANTICS`](../api/macros/json_brace_init_copy_semantics.md) macro.
|
||||
|
||||
## Building incrementally
|
||||
|
||||
A value can also be built up piece by piece. Accessing a non-existing object key or array index with
|
||||
[`operator[]`](element_access/unchecked_access.md) creates the element on the fly:
|
||||
|
||||
```cpp
|
||||
json j; // null
|
||||
j["answer"]["everything"] = 42; // becomes an object
|
||||
j["list"] = {1, 0, 2};
|
||||
j["list"].push_back(3); // [1,0,2,3]
|
||||
```
|
||||
|
||||
See [modifying values](modifying_values.md) for [`push_back`](../api/basic_json/push_back.md),
|
||||
[`emplace`](../api/basic_json/emplace.md), and related functions.
|
||||
|
||||
## With the `_json` literal
|
||||
|
||||
The `_json` [user-defined literal](../api/operator_literal_json.md) parses a string at the call site and is a
|
||||
convenient way to write a JSON value inline:
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/operator_literal_json.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/operator_literal_json.output"
|
||||
```
|
||||
|
||||
Note this **parses** the string, so `#!cpp "42"_json` is the number `#!cpp 42`, whereas `#!cpp json("42")` is the JSON
|
||||
string `#!json "42"`.
|
||||
|
||||
## See also
|
||||
|
||||
- [`basic_json` constructors](../api/basic_json/basic_json.md) - all ways to construct a value
|
||||
- [`array`](../api/basic_json/array.md) / [`object`](../api/basic_json/object.md) - force array or object type
|
||||
- [`operator""_json`](../api/operator_literal_json.md) - the `_json` literal
|
||||
- [Converting values](conversions.md) - which C++ types can be used
|
||||
- [Parsing](parsing/index.md) - create a value from JSON text
|
||||
@@ -29,7 +29,7 @@ otherwise.
|
||||
| `#!cpp j.at("hobbies").at(0)` | `#!json "hiking"` |
|
||||
| `#!cpp j.at("hobbies").at(1)` | `#!json "reading"` |
|
||||
|
||||
The return value is a reference, so it can be modified by the original value.
|
||||
The return value is a reference, so it can be used to modify the original value.
|
||||
|
||||
??? example "Write access"
|
||||
|
||||
@@ -62,7 +62,7 @@ non-existing, an exception is thrown.
|
||||
[json.exception.out_of_range.401] array index 3 is out of range
|
||||
```
|
||||
|
||||
When you [extended diagnostic messages](../../home/exceptions.md#extended-diagnostic-messages) are enabled by
|
||||
When [extended diagnostic messages](../../home/exceptions.md#extended-diagnostic-messages) are enabled by
|
||||
defining [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md), the exception further gives information where
|
||||
the key or index is missing or out of range.
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
In many situations, such as configuration files, missing values are not exceptional, but may be treated as if a default
|
||||
value was present. For this case, use [`value(key, default_value)`](../../api/basic_json/value.md) which takes the key
|
||||
you want to access and a default value in case there is no value stored with that key.
|
||||
you want to access and a default value in case there is no value stored with that key. This is equivalent to Python's
|
||||
`dict.get(key, default)`.
|
||||
|
||||
## Example
|
||||
|
||||
@@ -41,7 +42,7 @@ you want to access and a default value in case there is no value stored with tha
|
||||
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[]`](../../api/basic_json/operator[].md). However,
|
||||
when we call `value` and provide `#!c 0` as default value, then `#!c -1` is returned. The occurs, because `#!c 0`
|
||||
when we call `value` 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
|
||||
|
||||
@@ -102,6 +102,20 @@ that the passed index is the new maximal index. Intermediate values are filled w
|
||||
`operator[]` can only be used with objects (with a string argument) or with arrays (with a numeric argument). For
|
||||
other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error305) is thrown.
|
||||
|
||||
## Performance: reserving array capacity
|
||||
|
||||
There is no public `reserve(count)` member on `basic_json` for pre-allocating array capacity. If you are building
|
||||
a large array incrementally (e.g., via repeated `push_back()`) and know its final size ahead of time, you can
|
||||
reserve capacity via `get_ref()` to access the underlying `array_t` directly:
|
||||
|
||||
```cpp
|
||||
json j = json::array();
|
||||
j.get_ref<json::array_t&>().reserve(1000);
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
j.push_back(i);
|
||||
}
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
| scenario | non-const value | const value |
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Features
|
||||
|
||||
This section describes the features of the library in detail. If you are new to the library, the pages below are
|
||||
roughly ordered along a typical workflow: create or parse a value, access and modify it, convert it to and from your own
|
||||
C++ types, and finally serialize it again.
|
||||
|
||||
## Creating and reading values
|
||||
|
||||
- [Creating JSON values](creating_values.md) — build values from literals, initializer lists, and STL containers, and
|
||||
understand the `#!cpp {}` vs. `#!cpp []` ambiguity.
|
||||
- [Parsing](parsing/index.md) — read a JSON value from a string, file, or stream, including
|
||||
[JSON Lines](parsing/json_lines.md), [callbacks](parsing/parser_callbacks.md), the
|
||||
[SAX interface](parsing/sax_interface.md), and [error handling](parsing/parse_exceptions.md).
|
||||
- [Comments](comments.md) and [trailing commas](trailing_commas.md) — opt-in relaxations of the JSON grammar.
|
||||
|
||||
## Accessing and modifying values
|
||||
|
||||
- [Element access](element_access/index.md) — unchecked ([`operator[]`](element_access/unchecked_access.md)),
|
||||
checked ([`at`](element_access/checked_access.md)), and access with a
|
||||
[default value](element_access/default_value.md).
|
||||
- [JSON Pointer](json_pointer.md) — address values deep inside a document with [RFC 6901](https://tools.ietf.org/html/rfc6901) pointers.
|
||||
- [Iterators](iterators.md) — traverse arrays and objects.
|
||||
- [Modifying values](modifying_values.md) — add, update, merge, and remove elements.
|
||||
- [JSON Patch and Diff](json_patch.md) and [JSON Merge Patch](merge_patch.md) — apply and compute structured changes.
|
||||
|
||||
## Converting to and from C++ types
|
||||
|
||||
- [Converting values](conversions.md) — get values out with [`get`](../api/basic_json/get.md)/[`get_to`](../api/basic_json/get_to.md),
|
||||
and understand implicit conversions.
|
||||
- [Arbitrary types conversions](arbitrary_types.md) — teach the library about your own structs and classes.
|
||||
- [Specializing enum conversion](enum_conversion.md) — map enums to strings instead of integers.
|
||||
|
||||
## Serializing values
|
||||
|
||||
- [Serialization](serialization.md) — turn a value back into JSON text with [`dump`](../api/basic_json/dump.md),
|
||||
including pretty-printing and handling of non-ASCII and invalid UTF-8.
|
||||
- [Binary formats](binary_formats/index.md) — encode values more compactly as
|
||||
[BJData](binary_formats/bjdata.md), [BSON](binary_formats/bson.md), [CBOR](binary_formats/cbor.md),
|
||||
[MessagePack](binary_formats/messagepack.md), or [UBJSON](binary_formats/ubjson.md).
|
||||
- [Binary values](binary_values.md) — store and exchange raw byte sequences.
|
||||
|
||||
## How values are stored and configured
|
||||
|
||||
- [Types](types/index.md) and [number handling](types/number_handling.md) — how JSON types map to C++ types and how
|
||||
numbers are treated.
|
||||
- [Object order](object_order.md) — keep insertion order with [`ordered_json`](../api/ordered_json.md).
|
||||
- [Runtime assertions](assertions.md), [supported macros](macros.md), the [`nlohmann` namespace](namespace.md), and
|
||||
[C++ modules](modules.md) — build-time and runtime configuration.
|
||||
|
||||
!!! tip "Looking for a specific function?"
|
||||
|
||||
This section gives conceptual overviews. For the precise signature, parameters, and return value of a function, see
|
||||
the [API Documentation](../api/basic_json/index.md).
|
||||
@@ -130,7 +130,7 @@ for (auto& [key, val] : j_object.items())
|
||||
|
||||
### Iterating strings and binary values
|
||||
|
||||
Note that "value" means a JSON value in this setting, not values stored in the underlying containers. That is, `*begin()` returns the complete string or binary array and is also safe the underlying string or binary array is empty.
|
||||
Note that "value" means a JSON value in this setting, not values stored in the underlying containers. That is, `*begin()` returns the complete string or binary array and is also safe if the underlying string or binary array is empty.
|
||||
|
||||
??? example
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ The library can also calculate a JSON patch (i.e., a **diff**) given two JSON va
|
||||
|
||||
For two JSON values *source* and *target*, the following code yields always true:
|
||||
|
||||
```cüü
|
||||
```cpp
|
||||
source.patch(diff(source, target)) == target;
|
||||
```
|
||||
|
||||
|
||||
@@ -77,6 +77,11 @@ auto val2 = j.at(json::json_pointer("/nested/three/1")); // false
|
||||
auto val3 = j.value(json::json_pointer("/nested/four"), 0); // 0
|
||||
```
|
||||
|
||||
!!! note "Creating intermediate levels that don't exist"
|
||||
|
||||
See the [`operator[]` notes](../api/basic_json/operator%5B%5D.md#return-value) for how array vs. object is
|
||||
decided when a pointer creates intermediate levels that don't exist yet.
|
||||
|
||||
## Flatten / unflatten
|
||||
|
||||
The library implements a function [`flatten`](../api/basic_json/flatten.md) to convert any JSON document into a JSON
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# Modifying values
|
||||
|
||||
Once a JSON value exists, its content can be changed: elements can be added, replaced, merged, and removed. This page
|
||||
gives an overview of the available operations. For read access, see [element access](element_access/index.md).
|
||||
|
||||
## Adding to arrays
|
||||
|
||||
New elements are appended to an array with [`push_back`](../api/basic_json/push_back.md) or constructed in place with
|
||||
[`emplace_back`](../api/basic_json/emplace_back.md). If the value is `#!json null`, it is converted to an array first, so
|
||||
these functions can also be used to build an array from scratch.
|
||||
|
||||
```cpp
|
||||
json j; // null
|
||||
j.push_back(1); // [1]
|
||||
j.push_back(2); // [1,2]
|
||||
j.emplace_back(3); // [1,2,3]
|
||||
|
||||
// operator+= is a shorthand for push_back
|
||||
j += 4; // [1,2,3,4]
|
||||
```
|
||||
|
||||
## Adding to objects
|
||||
|
||||
The most common way to add or replace a member is [`operator[]`](element_access/unchecked_access.md), which inserts the
|
||||
key if it does not exist yet:
|
||||
|
||||
```cpp
|
||||
json j;
|
||||
j["name"] = "Mary"; // {"name":"Mary"}
|
||||
j["name"] = "John"; // {"name":"John"} (replaced)
|
||||
```
|
||||
|
||||
[`emplace`](../api/basic_json/emplace.md) inserts a member only if the key is not already present, and reports whether
|
||||
the insertion happened — useful for "add if absent" semantics.
|
||||
|
||||
## Merging objects
|
||||
|
||||
To merge one object into another, [`update`](../api/basic_json/update.md) copies all members from another object,
|
||||
overwriting existing keys (similar to Python's `dict.update`). This is the idiomatic way to combine two objects.
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/update.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/update.output"
|
||||
```
|
||||
|
||||
For a recursive merge that follows [RFC 7386](https://tools.ietf.org/html/rfc7386), see
|
||||
[JSON Merge Patch](merge_patch.md). To apply a sequence of well-defined edit operations, see
|
||||
[JSON Patch](json_patch.md).
|
||||
|
||||
## Removing elements
|
||||
|
||||
Elements are removed with [`erase`](../api/basic_json/erase.md), which accepts an object key, an array index, or an
|
||||
iterator. [`clear`](../api/basic_json/clear.md) empties a value while keeping its type, and
|
||||
[`operator[]`](element_access/unchecked_access.md) combined with assignment can overwrite a value entirely.
|
||||
|
||||
```cpp
|
||||
json j = {{"a", 1}, {"b", 2}, {"c", 3}};
|
||||
j.erase("b"); // {"a":1,"c":3}
|
||||
|
||||
json a = {1, 2, 3, 4};
|
||||
a.erase(1); // [1,3,4] (erase by index)
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [`push_back`](../api/basic_json/push_back.md) / [`emplace_back`](../api/basic_json/emplace_back.md) - append to an array
|
||||
- [`emplace`](../api/basic_json/emplace.md) - insert into an object if the key is absent
|
||||
- [`update`](../api/basic_json/update.md) - merge objects
|
||||
- [`erase`](../api/basic_json/erase.md) / [`clear`](../api/basic_json/clear.md) - remove elements
|
||||
- [JSON Patch and Diff](json_patch.md) and [JSON Merge Patch](merge_patch.md) - structured modifications
|
||||
@@ -27,6 +27,7 @@ json data = json::parse(f);
|
||||
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`
|
||||
@@ -38,3 +39,21 @@ Only the following symbols are exported from `nlohmann.json`:
|
||||
- `nlohmann::to_string`
|
||||
- `nlohmann::literals::json_literals::operator""_json`
|
||||
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
||||
|
||||
Additionally, the following `nlohmann::detail` symbols are exported, solely to work around an MSVC compilation issue
|
||||
([#3970](https://github.com/nlohmann/json/issues/3970)). They are implementation details, not part of the public API,
|
||||
and should not be used directly:
|
||||
|
||||
- `nlohmann::detail::json_sax_dom_callback_parser`
|
||||
- `nlohmann::detail::unknown_size`
|
||||
|
||||
## Known issues
|
||||
|
||||
C++20 modules support is exercised in CI against current GCC and Clang on Ubuntu, and the default MSVC toolset on Windows Server 2022 — there is no documented minimum compiler version, unlike feature-test-macro-gated features such as [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md).
|
||||
|
||||
!!! info "Known compiler issues"
|
||||
|
||||
- **GCC** may emit "redefinition" errors when `#include <nlohmann/json.hpp>` appears in a module preamble together with other imports. This is an upstream GCC bug, not yet resolved as of GCC 16. Workarounds: include `nlohmann/json.hpp` before other `#include`s, use `import nlohmann.json;` instead, or upgrade GCC. ([issue #5103](https://github.com/nlohmann/json/issues/5103))
|
||||
- **MSVC** could fail with `C2039: 'json_sax_dom_callback_parser' is not a member of ... detail`; fixed by exporting the required internal symbols from `json.cppm` (see [Exported symbols](#exported-symbols) above). ([issue #3970](https://github.com/nlohmann/json/issues/3970))
|
||||
|
||||
If you hit a different module-related build failure, search [existing issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+modules) before filing a new one.
|
||||
|
||||
@@ -59,7 +59,7 @@ may complain about undefined references.
|
||||
|
||||
Different versions are not necessarily ABI-incompatible, but the project does not actively track changes in the ABI and
|
||||
recommends that all parts of a codebase exchanging library types be built with the same version. Users can, **at their
|
||||
own risk**, disable the version component of the linline namespace, allowing different versions – but not
|
||||
own risk**, disable the version component of the inline namespace, allowing different versions – but not
|
||||
configurations – to be used in cases where the linker would otherwise output undefined reference errors.
|
||||
|
||||
To do so, define [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](../api/macros/nlohmann_json_namespace_no_version.md) to `1`.
|
||||
@@ -71,6 +71,7 @@ section to emulate the effect of the `NLOHMANN_JSON_NAMESPACE_NO_VERSION` macro.
|
||||
|
||||
Disabling the namespace version component and mixing ABI-incompatible versions will result in crashes or incorrect
|
||||
behavior. You have been warned!
|
||||
|
||||
## Disabling the inline namespace completely
|
||||
|
||||
When interoperability with code using a pre-3.11.0 version of the library is required, users can, **at their own risk**
|
||||
|
||||
@@ -37,7 +37,7 @@ The default type `nlohmann::json` uses a `std::map` to store JSON objects, and t
|
||||
|
||||
## Alternative behavior: preserve insertion order
|
||||
|
||||
If you do want to preserve the **insertion order**, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179).
|
||||
If you do want to preserve the **insertion order**, you can use the type [`nlohmann::ordered_json`](../api/ordered_json.md).
|
||||
|
||||
??? example
|
||||
|
||||
@@ -103,7 +103,7 @@ Assume file `input.json` contains the JSON object above:
|
||||
```json
|
||||
{
|
||||
"one": 1,
|
||||
"three": 3
|
||||
"two": 2,
|
||||
"three": 3,
|
||||
"two": 2
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,13 +1,61 @@
|
||||
# Parsing
|
||||
|
||||
!!! note
|
||||
|
||||
This page is under construction.
|
||||
This library can create a JSON value from a wide range of inputs. This page gives an overview of the available parsing
|
||||
functions and how they behave; the linked pages go into more detail.
|
||||
|
||||
## Input
|
||||
|
||||
The [`parse`](../../api/basic_json/parse.md) function reads a JSON value from an input. The input can be
|
||||
|
||||
- a string (`#!cpp std::string`, C string, or string literal),
|
||||
- a `#!cpp std::istream` (e.g., an `#!cpp std::ifstream` reading from a file),
|
||||
- a `#!cpp FILE*` pointer,
|
||||
- a pair of iterators over a contiguous range (e.g., a `#!cpp std::vector<std::uint8_t>`), or
|
||||
- a contiguous container.
|
||||
|
||||
```cpp
|
||||
// parse from a string
|
||||
json j = json::parse(R"({"happy": true, "pi": 3.141})");
|
||||
|
||||
// parse from a file
|
||||
std::ifstream f("example.json");
|
||||
json data = json::parse(f);
|
||||
```
|
||||
|
||||
The input must be encoded in UTF-8; other encodings are not supported. A single input may contain only one JSON value.
|
||||
Inputs consisting of multiple values separated by newlines are handled by the [JSON Lines](json_lines.md) format.
|
||||
|
||||
By default, the library rejects comments and trailing commas. Both can be enabled with parameters of the `parse`
|
||||
function — see [comments](../comments.md) and [trailing commas](../trailing_commas.md).
|
||||
|
||||
## SAX vs. DOM parsing
|
||||
|
||||
The library offers two parsing models:
|
||||
|
||||
- **DOM parsing** (the default): the complete input is read and stored as an in-memory `basic_json` value that can be
|
||||
traversed and modified freely. This is what [`parse`](../../api/basic_json/parse.md) does, and it is the right choice
|
||||
for most use cases.
|
||||
- **SAX parsing**: instead of building a value, the parser reports events (such as "a string was read" or "an object
|
||||
started") to a handler that you implement. This avoids building the full value in memory and is useful for very large
|
||||
inputs or when you only need to extract parts of the input. See the [SAX interface](sax_interface.md) for details and
|
||||
[`sax_parse`](../../api/basic_json/sax_parse.md) for the API.
|
||||
|
||||
You can influence a DOM parse without switching to the SAX interface by passing a
|
||||
[parser callback](parser_callbacks.md), which is called during parsing and can, for example, discard parts of the input.
|
||||
|
||||
## Exceptions
|
||||
|
||||
See [parsing and exceptions](parse_exceptions.md).
|
||||
When the input is not valid JSON, the `parse` function throws an exception by default. If exceptions are undesired or
|
||||
unavailable, the parser can instead return a discarded value, or [`accept`](../../api/basic_json/accept.md) can be used
|
||||
to only check whether an input is valid JSON. See [parsing and exceptions](parse_exceptions.md) for the available
|
||||
options.
|
||||
|
||||
## See also
|
||||
|
||||
- [`parse`](../../api/basic_json/parse.md) - deserialize from a compatible input
|
||||
- [`accept`](../../api/basic_json/accept.md) - check if the input is valid JSON
|
||||
- [`sax_parse`](../../api/basic_json/sax_parse.md) - generate SAX events
|
||||
- [JSON Lines](json_lines.md) - parse newline-delimited JSON
|
||||
- [parser callbacks](parser_callbacks.md) - influence the parsing by a callback function
|
||||
- [SAX interface](sax_interface.md) - implement a custom SAX handler
|
||||
- [parsing and exceptions](parse_exceptions.md) - control error handling
|
||||
|
||||
@@ -47,3 +47,6 @@ JSON Lines input with more than one value is treated as invalid JSON by the [`pa
|
||||
```
|
||||
|
||||
with a JSON Lines input does not work, because the parser will try to parse one value after the last one.
|
||||
|
||||
This is different from parsing a stream of *concatenated* (non-newline-delimited) JSON values, for which
|
||||
`operator>>` does work -- see its [notes](../../api/operator_gtgt.md#notes) for details.
|
||||
|
||||
@@ -58,6 +58,14 @@ table describes the values of the parameters `depth`, `event`, and `parsed`.
|
||||
| `array_end` | 1 | `#!json [52.519444,13.406667]` |
|
||||
| `object_end` | 0 | `#!json {"location":[52.519444,13.406667],"name":"Berlin"}` |
|
||||
|
||||
!!! note "No built-in nesting depth limit"
|
||||
|
||||
The library has no built-in limit on recursion/nesting depth while parsing. A parser callback can only
|
||||
*discard* content it has already parsed (by returning `#!c false`); it cannot make parsing fail once a
|
||||
nesting limit is exceeded partway through reading a deeply nested value. If you need to reject over-deep
|
||||
untrusted input outright, track `depth` in a callback and `throw` from it once your limit is exceeded (a
|
||||
thrown exception propagates out of `parse()` as usual).
|
||||
|
||||
## Return value
|
||||
|
||||
Discarding a value (i.e., returning `#!c false`) has different effects depending on the context in which the function
|
||||
@@ -81,3 +89,82 @@ was called:
|
||||
```json
|
||||
--8<-- "examples/parse__string__parser_callback_t.output"
|
||||
```
|
||||
|
||||
## Recipe: rejecting duplicate object keys
|
||||
|
||||
The JSON specification leaves the handling of objects with repeated keys up to the implementation. As described in
|
||||
[`object_t`](../../api/basic_json/object_t.md#behavior), it is unspecified which value for a repeated key ends up in
|
||||
the resulting `#!c json` value -- once parsing has produced that value, the duplicate is already gone, because object
|
||||
storage maps each key to a single value. If duplicate keys should instead be treated as an error, a parser callback
|
||||
can detect them while the object is still being read, before that ambiguity ever applies.
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/reject_duplicate_keys.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/reject_duplicate_keys.output"
|
||||
```
|
||||
|
||||
This approach has two limitations:
|
||||
|
||||
- The depth-indexed bookkeeping must account for the fact that `object_start` reports the depth of the *parent* of
|
||||
the object, while the `key` events inside that object are reported one depth deeper (see the event table above);
|
||||
it is easy to get this off by one for nested objects.
|
||||
- The thrown exception cannot carry a `parse_error`-style byte offset, because position tracking only exists inside
|
||||
the parser and lexer, not at the callback layer.
|
||||
|
||||
For strict validation with precise error positions, implementing a [SAX interface](sax_interface.md) instead gives
|
||||
access to the parser's position information directly.
|
||||
|
||||
## Recipe: streaming a large homogeneous array
|
||||
|
||||
A common use case is a huge top-level array of many similarly-shaped objects, too large to hold entirely in
|
||||
memory as a `#!c json` value. A parser callback can hand off each completed element to a user function and then
|
||||
discard it, so memory usage stays bounded by a single element (plus the not-yet-parsed tail of the input) rather
|
||||
than the whole document. Since the top-level array's `array_start`/`array_end` are reported at `depth == 0` (its
|
||||
parent is the document root), the object elements it contains are reported at `depth == 1`:
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
std::ifstream input("large_array.json");
|
||||
|
||||
auto callback = [](int depth, json::parse_event_t event, json& parsed) -> bool {
|
||||
if (depth == 1 && event == json::parse_event_t::object_end) {
|
||||
handle_element(parsed); // process the element, e.g. write it elsewhere
|
||||
return false; // discard it -- frees its memory before the next one is parsed
|
||||
}
|
||||
return true; // keep everything else, including the (by then empty) top-level array
|
||||
};
|
||||
|
||||
json::parse(input, callback);
|
||||
```
|
||||
|
||||
If the array's elements are scalars or nested arrays instead of objects, check for `parse_event_t::value` or
|
||||
`parse_event_t::array_end` at `depth == 1` instead. The same approach works for a top-level *object* of many
|
||||
homogeneous values by checking `object_end`/`value` events at `depth == 1` there too.
|
||||
|
||||
## Recipe: max nesting depth via a callback
|
||||
|
||||
Since there is no built-in nesting-depth limit (see the note above), a callback can enforce one manually by
|
||||
tracking the maximum `depth` seen and throwing once it is exceeded:
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
constexpr int max_depth = 32;
|
||||
|
||||
auto callback = [](int depth, json::parse_event_t /*event*/, json& /*parsed*/) -> bool {
|
||||
if (depth > max_depth) {
|
||||
throw std::runtime_error("maximum nesting depth exceeded");
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
json::parse(input, callback);
|
||||
```
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
# Serialization
|
||||
|
||||
Serialization is the process of turning a JSON value back into JSON text. It is the counterpart to
|
||||
[parsing](parsing/index.md). The central function is [`dump`](../api/basic_json/dump.md), which returns the JSON text as
|
||||
a string.
|
||||
|
||||
```cpp
|
||||
json j = {{"pi", 3.141}, {"happy", true}};
|
||||
|
||||
std::string s = j.dump(); // {"happy":true,"pi":3.141}
|
||||
```
|
||||
|
||||
To write a value directly to a stream (for example, a file or `#!cpp std::cout`), the
|
||||
[`operator<<`](../api/operator_ltlt.md) is provided:
|
||||
|
||||
```cpp
|
||||
std::cout << j << std::endl;
|
||||
```
|
||||
|
||||
!!! note "String, not raw value"
|
||||
|
||||
`dump` always returns a **JSON text**. Serializing a JSON string therefore includes the surrounding quotes and
|
||||
escapes special characters. To obtain the *contained* string value without quotes, use
|
||||
[`get<std::string>()`](conversions.md) instead of `dump`. See the [converting values](conversions.md) page.
|
||||
|
||||
## Pretty-printing
|
||||
|
||||
By default, `dump` produces the most compact representation without any superfluous whitespace. Passing a non-negative
|
||||
`indent` argument pretty-prints the output with the given number of spaces per level:
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/dump.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/dump.output"
|
||||
```
|
||||
|
||||
The indentation character can be changed with the second argument (e.g., a tab `#!cpp '\t'`). An `indent` of `0` inserts
|
||||
newlines but no leading spaces, and the default of `#!cpp -1` selects the compact single-line form.
|
||||
|
||||
## Non-ASCII characters
|
||||
|
||||
Strings are stored and serialized as UTF-8 (see [types](types/index.md#strings)). By default, `dump` copies valid
|
||||
non-ASCII characters as-is. Setting the third argument `ensure_ascii` to `#!cpp true` escapes all non-ASCII characters
|
||||
with `\uXXXX` sequences, so that the output contains only ASCII characters:
|
||||
|
||||
```cpp
|
||||
json j = "苹果";
|
||||
j.dump(); // "苹果"
|
||||
j.dump(-1, ' ', true); // "苹果"
|
||||
```
|
||||
|
||||
## Handling invalid UTF-8
|
||||
|
||||
If a string contains invalid UTF-8 sequences (for example, because it holds data in another encoding such as Latin-1),
|
||||
serialization fails by default. The fourth argument of `dump` selects an
|
||||
[`error_handler`](../api/basic_json/error_handler_t.md):
|
||||
|
||||
- `strict` (default) — throw a [`type_error.316`](../home/exceptions.md#jsonexceptiontype_error316) exception.
|
||||
- `replace` — replace invalid bytes with the Unicode replacement character U+FFFD (`�`).
|
||||
- `ignore` — silently drop invalid bytes.
|
||||
|
||||
??? example
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/error_handler_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/error_handler_t.output"
|
||||
```
|
||||
|
||||
!!! tip "Avoiding invalid UTF-8"
|
||||
|
||||
The best fix is to ensure that all strings are UTF-8 encoded before storing them. See the
|
||||
[FAQ on non-ASCII characters](../home/faq.md#parse-errors-reading-non-ascii-characters) for how to convert wide or
|
||||
Latin-1 strings.
|
||||
|
||||
## Numbers, NaN, and binary values
|
||||
|
||||
- **Numbers** are serialized with enough precision to round-trip; see [number serialization](types/number_handling.md#number-serialization).
|
||||
- **NaN and infinity** cannot be represented in JSON and are serialized as `#!json null`; see
|
||||
[NaN handling](types/number_handling.md#nan-handling). The [binary formats](binary_formats/index.md) can preserve
|
||||
them.
|
||||
- **Binary values** have no JSON representation and are serialized as a helper object for debugging only; see
|
||||
[binary values](binary_values.md#serialization).
|
||||
|
||||
## Using `std::format`, `std::print`, and `fmt`
|
||||
|
||||
Since version 3.12.0, JSON values can be formatted directly with C++20's
|
||||
[`std::format`](https://en.cppreference.com/w/cpp/utility/format/format) whenever the standard library provides the
|
||||
`<format>` header (controlled by [`JSON_HAS_STD_FORMAT`](../api/macros/json_has_std_format.md)). This is enabled by the
|
||||
[`std::formatter<basic_json>`](../api/basic_json/std_formatter.md) specialization, which also makes JSON values work with
|
||||
`std::format_to` and with C++23's `std::print`/`std::println`:
|
||||
|
||||
```cpp
|
||||
std::print("{}", j); // compact, like j.dump()
|
||||
std::print("{:2}", j); // pretty-printed with indent 2 (like j.dump(2))
|
||||
std::println("{:#}", j); // pretty-printed with the default indent
|
||||
```
|
||||
|
||||
The format spec mirrors the `dump` parameters: `#!cpp "{:#}"` pretty-prints, a width such as `#!cpp "{:2}"` sets the
|
||||
indent, and a fill-and-align prefix such as `#!cpp "{:.>#}"` sets the indent character.
|
||||
|
||||
For the [{fmt}](https://github.com/fmtlib/fmt) library, the library ships a
|
||||
[`format_as`](../api/basic_json/format_as.md) helper. Note its behavior depends on the `fmt` version; see the
|
||||
[FAQ entry](../home/faq.md#using-json-values-with-stdformat-or-fmt) for the details and a recipe for a full
|
||||
`fmt::formatter` specialization.
|
||||
|
||||
## Serializing to other formats
|
||||
|
||||
Besides JSON text, a value can also be serialized to the more compact [binary formats](binary_formats/index.md)
|
||||
(BJData, BSON, CBOR, MessagePack, UBJSON).
|
||||
|
||||
## See also
|
||||
|
||||
- [`dump`](../api/basic_json/dump.md) - serialize to a JSON-formatted string
|
||||
- [`operator<<`](../api/operator_ltlt.md) - serialize to a stream
|
||||
- [`to_string`](../api/basic_json/to_string.md) - user-defined-conversion helper
|
||||
- [`std::formatter<basic_json>`](../api/basic_json/std_formatter.md) - use JSON values with `std::format` and `std::print`
|
||||
- [`format_as`](../api/basic_json/format_as.md) - use JSON values with the {fmt} library
|
||||
- [Parsing](parsing/index.md) - the reverse operation
|
||||
@@ -131,13 +131,13 @@ std::map<
|
||||
The choice of `object_t` influences the behavior of the JSON class. With the default type, objects have the following behavior:
|
||||
|
||||
- When all names are unique, objects will be interoperable in the sense that all software implementations receiving that object will agree on the name-value mappings.
|
||||
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or `#!json {"key": 2}`.
|
||||
- When the names within an object are not unique, it is unspecified which one of the values for a given key will be chosen. For instance, `#!json {"key": 2, "key": 1}` could be equal to either `#!json {"key": 1}` or `#!json {"key": 2}`. To reject duplicate keys instead of silently resolving them one way or another, see [this parsing recipe](../parsing/parser_callbacks.md#recipe-rejecting-duplicate-object-keys).
|
||||
- Internally, name/value pairs are stored in lexicographical order of the names. Objects will also be serialized (see `dump`) in this order. For instance, both `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be stored and serialized as `#!json {"a": 2, "b": 1}`.
|
||||
- When comparing objects, the order of the name/value pairs is irrelevant. This makes objects interoperable in the sense that they will not be affected by these differences. For instance, `#!json {"b": 1, "a": 2}` and `#!json {"a": 2, "b": 1}` will be treated as equal.
|
||||
|
||||
### Key order
|
||||
|
||||
The order name/value pairs are added to the object are *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON objects.
|
||||
The order in which name/value pairs are added to the object is *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON objects.
|
||||
|
||||
### Limits
|
||||
|
||||
@@ -151,6 +151,18 @@ In this class, the object's limit of nesting is not explicitly constrained. Howe
|
||||
|
||||
Objects are stored as pointers in a `basic_json` type. That is, for any access to object values, a pointer of type `object_t*` must be dereferenced.
|
||||
|
||||
### Converting maps with non-string keys
|
||||
|
||||
A `std::map`/`std::unordered_map` whose key type is not string-like (e.g., `std::map<int, std::string>`) is
|
||||
converted to a JSON *array* of 2-element `[key, value]` arrays rather than a JSON object, because JSON object
|
||||
keys must be strings:
|
||||
|
||||
```cpp
|
||||
std::map<int, std::string> m{{1, "one"}, {2, "two"}};
|
||||
json j = m;
|
||||
// j is [[1,"one"],[2,"two"]], not {"1":"one","2":"two"}
|
||||
```
|
||||
|
||||
|
||||
## Arrays
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ In the default [`json`](../../api/json.md) type, numbers are stored as `#!c std:
|
||||
number without loss of precision. If this is impossible (e.g., if the number is too large), the number is stored as
|
||||
`#!c double`.
|
||||
|
||||
Positive integers are stored as `#!c std::uint64_t`, while negative integers are stored as `#!c std::int64_t`. This
|
||||
distinction is determined at parse time: if the JSON number has a leading minus sign, it uses signed integer storage;
|
||||
otherwise, it uses unsigned integer storage.
|
||||
|
||||
!!! info "Notes"
|
||||
|
||||
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
|
||||
@@ -91,7 +95,7 @@ This is the same behavior as the code `#!c double x = 3.141592653589793238462643
|
||||
|
||||
!!! success "Interoperability"
|
||||
|
||||
- The library interoperable with respect to the specification, because its supported range $[-2^{63}, 2^{64}-1]$ is
|
||||
- The library is interoperable with respect to the specification, because its supported range $[-2^{63}, 2^{64}-1]$ is
|
||||
larger than the described range $[-2^{53}+1, 2^{53}-1]$.
|
||||
- All integers outside the range $[-2^{63}, 2^{64}-1]$, as well as floating-point numbers are stored as `double`.
|
||||
This also concurs with the specification above.
|
||||
@@ -153,7 +157,7 @@ NaN (not-a-number) cannot be expressed with the number syntax described above an
|
||||
|
||||
That is, there is no way to *parse* a NaN value. However, assignments can store NaN values in a JSON value.
|
||||
|
||||
This library serializes NaN values as `#!js null`. This corresponds to the behavior of JavaScript's
|
||||
This library serializes NaN values as `#!js null`. This corresponds to the behavior of JavaScript's
|
||||
[`JSON.stringify`](https://www.w3schools.com/js/js_json_stringify.asp) function.
|
||||
|
||||
!!! example
|
||||
@@ -182,7 +186,7 @@ This library serializes NaN values as `#!js null`. This corresponds to the beha
|
||||
|
||||
### Number comparison
|
||||
|
||||
Floating-point inside JSON values numbers are compared with `#!c json::number_float_t::operator==` which is
|
||||
Floating-point numbers inside JSON values are compared with `#!c json::number_float_t::operator==` which is
|
||||
`#!c double::operator==` by default.
|
||||
|
||||
!!! example "Alternative comparison functions"
|
||||
@@ -203,8 +207,8 @@ Floating-point inside JSON values numbers are compared with `#!c json::number_fl
|
||||
```cpp
|
||||
bool my_equal(const_reference lhs, const_reference rhs)
|
||||
{
|
||||
const auto lhs_type lhs.type();
|
||||
const auto rhs_type rhs.type();
|
||||
const auto lhs_type = lhs.type();
|
||||
const auto rhs_type = rhs.type();
|
||||
if (lhs_type == rhs_type)
|
||||
{
|
||||
switch(lhs_type)
|
||||
@@ -230,7 +234,7 @@ Floating-point inside JSON values numbers are compared with `#!c json::number_fl
|
||||
### Number conversion
|
||||
|
||||
Just like the C++ language itself, the `get` family of functions allows conversions between unsigned and signed
|
||||
integers, and between integers and floating-point values to integers. This behavior may be surprising.
|
||||
integers, and between integers and floating-point values. This behavior may be surprising.
|
||||
|
||||
!!! warning "Unconditional number conversions"
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# Debugging
|
||||
|
||||
This page collects the library's built-in debugger integrations and other debugging-related features. They are
|
||||
not linked from a single place elsewhere in the docs, so are collected here.
|
||||
|
||||
## Visual Studio (natvis)
|
||||
|
||||
The repository ships [`nlohmann_json.natvis`](https://github.com/nlohmann/json/blob/develop/nlohmann_json.natvis)
|
||||
at its root, a [Natvis](https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects)
|
||||
file that gives `json`/`ordered_json` values a friendly, key/value debugger view instead of showing raw internal
|
||||
fields, when debugging with the MSVC debug engine (`cppvsdbg`) in Visual Studio or VS Code.
|
||||
|
||||
Debug engines that wrap LLDB instead of the MSVC debug engine (for example, `codelldb` in VS Code) only have
|
||||
partial/experimental Natvis support, and commonly fall back to showing raw internal fields even with the
|
||||
`.natvis` file present. Switching to `cppvsdbg` where available, or checking your debug extension's own Natvis
|
||||
support/version, are the next things to try if this happens. There is currently no bundled LLDB-native
|
||||
pretty-printer script in this repository.
|
||||
|
||||
## GDB
|
||||
|
||||
The repository ships a [GDB Python pretty printer](https://github.com/nlohmann/json/tree/develop/tools/gdb_pretty_printer)
|
||||
under `tools/gdb_pretty_printer`, with its own usage instructions in that directory's `README.md`.
|
||||
|
||||
## Extended exception diagnostics
|
||||
|
||||
Defining [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) before including the library augments
|
||||
`type_error`/`out_of_range`-style exceptions with a JSON Pointer to the offending value, which can help pinpoint
|
||||
where in a large document a runtime error occurred. This only applies to exceptions thrown *after* a value
|
||||
exists (e.g. during element access); parse errors, which happen before any value exists to point at, are not
|
||||
covered by this mechanism -- see [Parsing and exceptions](../features/parsing/parse_exceptions.md) for how parse
|
||||
errors report their own location instead.
|
||||
@@ -326,6 +326,9 @@ An unexpected byte was read in a [binary format](../features/binary_formats/inde
|
||||
```
|
||||
[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow
|
||||
```
|
||||
|
||||
### json.exception.parse_error.113
|
||||
|
||||
@@ -893,7 +896,7 @@ A JSON Patch `add` operation cannot be applied because the target location's par
|
||||
|
||||
!!! note
|
||||
|
||||
This exception was added in version 3.12.x. Before that, this situation hit an internal assertion (aborting the program in debug builds) or was silently ignored when assertions were disabled.
|
||||
This exception was added in version 3.13.0. Before that, this situation hit an internal assertion (aborting the program in debug builds) or was silently ignored when assertions were disabled.
|
||||
|
||||
## Further exceptions
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user