Compare commits

..
Author SHA1 Message Date
Niels Lohmann 4c3e92b96e Split the macOS and Windows jobs into a PR set, a full set, and a nightly set
The 19 macOS and 32 Windows jobs ran on every push to every pull request.
They now use the same sets as the Ubuntu jobs:

- PR set (16): four Visual Studio 2022 and two Visual Studio 2026
  configurations, ARM64 Debug, Clang 20.1.8 with MinGW, MinGW x86, the
  C++20 module test, Xcode 16.0, 16.4, 26.3 and 26.6, C++14 on the
  latest Xcode, and the Swift Package Manager check.
- full set (34): every other Visual Studio configuration, Clang
  version, clang-cl, Xcode version and C++ standard.
- nightly set (1): 64-bit MinGW, which takes about 68 minutes. A failed
  nightly run opens or updates an issue.

No configuration is removed: tools/ci_jobs/ci_jobs.py --compare lists
157 configurations before and after, and all jobs keep their runner,
steps and environment. ci_jobs.py now checks all three workflows and
expands matrices that consist only of include entries correctly.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 19:45:39 +01:00
Niels Lohmann 087df7b0c2 Split the Ubuntu jobs into a PR set, a full set, and a nightly set
All ~100 Ubuntu jobs ran on every push to every pull request. They now
belong to three sets, chosen by each job's if: condition:

- PR set (16 configurations): every push to a pull request and every
  push. Together with the checks that always run, these jobs would
  have caught at least 92 % of the failing commits of Sep/Oct 2026.
- full set (73 configurations): after the PR set passed, on pushes and
  on pull requests with the "🚀 ready to merge" label.
- nightly set (10 configurations): Infer, Valgrind, coverage, icpc,
  icpx, nvhpc, CUDA, and ARM64; nightly on develop, on pushes to master
  and release/*, and by hand. A failed nightly run opens or updates an
  issue.

A matrix whose entries belong to different sets is split into one job
per set; the jobs share their steps through YAML anchors. No
configuration is removed: tools/ci_jobs/ci_jobs.py --compare lists 150
configurations before and after. The same tool checks in CI that every
job belongs to exactly one set, that the full set waits for the whole
PR set, and that the job table in quality_assurance.md is up to date.

The documentation describes the sets in a new section "How CI runs",
and the QA pipeline figure shows the new badges.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 19:40:21 +01:00
Niels Lohmann eae3c8217b Split the checks of check_path_filters.py into smaller functions
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 19:39:20 +01:00
Niels Lohmann 960c234cc6 Do not report the excluded files that check_path_filters.py lists itself
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 18:58:36 +01:00
Niels Lohmann b6e24d19a9 Skip the compiler workflows for pull requests that change no build input
ubuntu.yml, macos.yml and windows.yml run about 155 jobs on every pull
request, including those that change only the documentation. They now
have a pull_request path filter: it starts with '**' and excludes the
documentation, Markdown files, GitHub metadata, other workflows and the
license files, so a new file runs them unless it is excluded on purpose.
Pushes to develop, master and release/* are not filtered.

The documentation jobs and the REUSE check move from ubuntu.yml to the
new repository_checks.yml, which has no path filter and also runs
tools/check_path_filters. That check keeps the three filters identical
and fails when a file the compiler jobs keep mentions an excluded file.
It found two: tools/check_build_options reads the Meson section of
package_managers.md, and the swiftpm job builds the Swift example from
the documentation; both are included in the filter.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 18:35:03 +01:00
Niels Lohmann 8617d9c94c Fix test lints that are red on develop (effc++, clang-tidy) (#5946)
- unit-bson: initialize the SAX recorder's member (-Weffc++)
- unit-json_patch: build the reference document independently instead of
  copying it (performance-unnecessary-copy-initialization)
- unit-json_view_builder: use node_kind::link instead of an out-of-range
  enum cast (clang-analyzer-optin.core.EnumCastOutOfRange)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 17:25:18 +01:00
Niels Lohmann eb8f675bc9 docs: explain signed zero in the diff() round-trip exceptions (#5944)
Spell out that numbers comparing equal produce no operation even if one is
zero and the other negative zero, in diff.md and features/json_patch.md.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 17:16:08 +01:00
Niels Lohmann 78a0687147 Strong exception guarantee for operator[](json_pointer) (#5940)
* Keep the value unchanged when operator[] with a JSON pointer throws

The non-const operator[](json_pointer) is documented with strong exception
safety, but get_unchecked created intermediate values while walking the
pointer and kept them when a later reference token failed, e.g.
json j; j["/a/99999999999999999999999"_json_pointer] threw 404 and left
{"a":[]}; padding an existing array or appending with "-" behaved alike,
and so did std::length_error/std::bad_alloc from a huge index.

get_unchecked now only walks existing values up to the last reference
token. The last token's key insertion or array growth is strongly
exception safe by itself. Any other change goes through
get_unchecked_create, which records the one change it makes to an existing
value (null converted, key inserted, array grown) in a RAII guard and
reverts it if a later step throws; everything else it creates lies below
that change. The guard needs no try/catch, so JSON_NOEXCEPTION builds are
unaffected. Successful calls create the same values as before.

Docs: state the guarantee in the exceptions list and version history of
operator[], fix the complexity of the pointer overloads of operator[] and
at, and warn that padding arrays up to an untrusted index allocates memory
proportional to the index (operator[].md, untrusted_input.md).

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

* Make the strongly exception-safe pointer operator[] faster than before

The previous commit made get_unchecked strongly exception safe but slower
with GCC 16 when it creates values (up to +6 % instructions for appending
with "-"). This restructures it so that no benchmark row is slower than
before the strong guarantee, with GCC 16, Clang 22 and Apple Clang.

- get_unchecked walks existing values in one loop that inserts nothing.
  The last reference token is resolved in that walk: "-" appends with
  emplace_back(), an index grows the array with operator[], and a missing
  key is inserted with emplace_hint() at the position the walk's
  lower_bound() found, so the key is searched once.
- With std::less<string_t> or std::less<> as comparator, the walk checks
  the key at the lower bound for equality instead of equivalence, which is
  the same for these comparators and cheaper.
- get_unchecked_create (not inlined) handles all other changes. Its guard
  swaps a null value with a fresh null value instead of copying it and
  reverts the change in a non-inlined function, so a successful call pays
  one compare for it. As every null value converted afterwards is a fresh
  one, it is converted in place instead of assigning a new array or object.
- Keys are added to new objects with emplace(), which also replaces the
  basic_json::operator[] call for ordered_json.

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

* Fix rollback of pointer operator[] for unusual object and string types

Follow-up to the strong exception guarantee of the non-const
operator[](json_pointer):

- get_unchecked_create assumed that emplace() always inserts the key that
  the walk did not find. For object types whose lookup and emplace()
  disagree (e.g. a copied fifo_map), nothing was inserted, the rollback
  erased the existing member, and the walk continued with a value of the
  wrong type (assertion, type_error.305, or a crash). It now checks the
  result of emplace(), arms the rollback only if a key was inserted, and
  otherwise continues the walk with the member found, as basic_json's
  operator[] does: such pointers throw out_of_range.404 and leave the value
  unchanged, as before the strong guarantee.
- The rollback erased the inserted key by key, which converts string_t to
  object_t::key_type and may allocate inside a noexcept function
  (std::terminate on bad_alloc with custom key types). It now erases by the
  iterator emplace() returned, and shrinks a grown array with erase() at
  the end instead of resize(). The documentation states the remaining
  requirement for custom template parameters.
- Creating values no longer calls string_t::begin(), so the non-const
  operator[](json_pointer) compiles with string types that lack it (as the
  alternative string type of the tests).
- Correct the @throw lists of get_unchecked and get_unchecked_create.

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

* Address review comments on operator[](json_pointer) rollback

- undo() shrinks the array with resize() instead of erase()
- comments say what "will be" done in get_unchecked_create
- tests: avoid a clang-tidy performance-unnecessary-copy-initialization
  hit (unit-alt-string) and the word "access" in section names, which
  Flawfinder flags as race/access

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

* Let the pointer rollback guard call undo() unconditionally

The check in the destructor and JSON_HEDLEY_NEVER_INLINE on undo() made no
measurable difference: instruction counts of j[ptr] are identical with
GCC 13 -O3 and within 0.4 % with clang, timings are within noise.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 17:15:55 +01:00
Niels Lohmann ebf5a176c4 Fix remaining red CI on develop: Infer null dereferences, clang-tidy redundant init (#5943) 2026-10-27 14:31:31 +01:00
Niels Lohmann a47170346a docs: new design for the documentation site (#5934)
* docs: new design for the documentation site

Apply the brand to the Material for MkDocs site: Inter and JetBrains Mono
served by the site (upright and real italic), brand colours, blue header band
with the syntax pattern, wordmark in the header, new home page (hero, cards,
animated feature tour), 404 page, polish for tabs, search, footer, focus
rings, tables and code blocks, and theme features (code copy, previous/next
footer, TOC follow, search suggestions).

Draw the number railroad diagram, the parser callback events and the iterator
illustrations as inline SVGs that follow the light and dark scheme. The
generator scripts are in docs/mkdocs/scripts/figures; the feature slideshow
(json-light.svg, json-dark.svg, replacing json.gif on the home page) is built
by docs/mkdocs/scripts/slideshow. Decision nodes in five flowcharts become
hexagons, which need far less room.

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

* docs: add figures, table captions and a macro chooser

- Figures with numbered captions: SAX stepper, json_view layout and edit
  stepper, exception map, JSON pointer and patch walkers, QA pipeline,
  scaling and binary size charts, roadmap lanes, release timeline,
  integration decision tree and namespace builder
- Table captions (nj-table-caption) on 9 pages
- Compile times: modules and PCH charts, filesystem section, re-measured
  Figure 1, links between features/modules.md and compile_times.md
- Interactive macro chooser for features/arbitrary_types.md
- Link check: exclude URLs that answer the plugin with 400/401/419 or are
  dead (customers.md)

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

* docs: macro chooser generates adl_serializer for non-default-constructible types

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

* docs: cross-link concept pages and API pages in See also sections

Add See also links in both directions between the concept pages (features,
home, integration) and the API pages, write API links in code font, give every
entry a comment after a dash, and show the callback event figure on the parser
callbacks page.

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

* docs: address review comments on the new design

- Home: add a "Latest release" button
- Sponsors: update the list and group it by tier
- Features: list all feature pages on the index page
- Releases: add highlights per release, link the 4.0 roadmap, add the first commit to the timeline
- Exceptions: prefix all example messages with the exception name
- API: no code font for format names in the See also links of the to_/from_ pages
- Merge Patch: show the document before, the patch, and the result
- Replace "--" with typographic dashes, mark external links with an icon, center Mermaid diagrams

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 07:41:42 +01:00
Niels Lohmann 2bb2feeef4 Fix the red CI on develop (json_view pointer tokens, bson, from_json tests, Infer, IWYU) (#5942)
* json_view: pointer tokens that cannot be array indices create objects

editable_document::set() chose an array for a null parent whenever the
token consisted of digits, so "01" threw parse_error.106 and the empty
token threw, while basic_json::operator[](json_pointer) has created an
object for such tokens since #5358. This broke
unit-json_view_edit_values on develop. Use the same RFC 6901 array index
test as basic_json.

Also re-indent the unflatten test that the astyle check flagged.

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

* Fix the other red jobs on develop

- unit-bson: initialize recorder::events in its declaration (-Weffc++)
- unit-json_view_from_json: suppress -Wexit-time-destructors for the
  serialize-enum tables and -Wfloat-equal for same()
- unit-pointer_access: @infer-ignore NULLPTR_DEREFERENCE for the
  dereferences after get_ptr() that Infer reports
- json_view.hpp: IWYU no_include for the detail headers that the view
  code uses through nlohmann/json.hpp

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

* Fix GCC warnings in the json_view from_json test

GCC (-Weffc++, -Wfloat-equal) rejected unit-json_view_from_json.cpp
(ci_test_standards_gcc (20)): initialize the members of shape and
with_names, and suppress -Wfloat-equal for GCC like for clang.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 07:27:34 +01:00
Niels Lohmann 21ec9bd801 json_view: fewer allocations when parsing small documents (#5915)
- Size the buffer of decoded strings on its first growth from the input (a
  quarter of it plus 16 bytes, at most 4 KiB) instead of 272 bytes, so that a
  document with escapes does not grow it twice, with a zero-filled copy each
  time.
- Allocate the node index of documents with an estimate of up to 1024 nodes
  (was 256) together with the header, which saves one allocation. When the
  estimate is too low (dense numbers), that block stays unused: at most 16 KiB
  instead of 4 KiB. shrink_to_fit() cannot release it separately; the
  documentation says so.

Fresh parse of a 2.5 KB minified tweet: 993 to 958 ns (-3.5 %), traverse and
select -3 %, with no row consistently slower (Apple M1 Max, 30 rounds, three
runs). Dense numeric documents parse about 9 % faster and keep up to 16 KiB
more memory.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-27 07:22:49 +01:00
Niels Lohmann 94fe31eb9b docs: writing generic code for json_view (#5924)
* docs: writing generic code for json_view

A "Writing generic code" section on the json_view page: why a function
taking json_view accepts no other view, the three signatures for
editable, read-only, or either kind of view (passed by value), why the
modes do not convert, is_json_view, and how a from_json() reads views
(constrained to json values and views; the macros and the library's
conversions do it already) with what differs then (duplicate keys,
JSON_DIAGNOSTICS paths).

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

* docs: name the documents the generic view function accepts

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

* docs: views of read-only documents convert to editable views

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 20:13:32 +01:00
Niels Lohmann 9e67bfa115 json_view: the library's std conversions read views directly (#5923)
* json_view: the library's std conversions read views directly

The library's from_json() overloads (containers, maps, std::array, C
arrays, pairs, tuples, optional, valarray, forward_list, enums, binary,
paths, and scalars) accept views: their traits use the view's
basic_json type, and the few accesses that differ (get_ptr) go through
small helpers. from_json() of a view now finds them; only the probe
still looks up by ADL only. get<T>() of a view thus converts these types
without materialize(), with the same values and exceptions; from an
object, a repeated key keeps the last value, as parse() does.

The view keeps its direct paths for vectors of the types it converts
directly (faster than from_json()) and for containers of views; its
other vector and map paths are replaced by from_json(). For basic_json,
std::valarray and std::forward_list are read in one pass (40 % and 3.5 %
fewer instructions); all other conversions are unchanged.

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

* json_view: enable_if_not_view_t instead of '!' in the from_json() templates

astyle spaces out the template argument list when it contains a negation;
the alias spells the condition with negation<> and leaves the lines alone.

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

* json_view: compact the template parameter lists astyle had spaced out

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 20:13:31 +01:00
Niels Lohmann e5fe4ebdd2 json_view: from_json() of the macros reads views directly (#5922)
get<T>() and get_to() of a view call T's from_json() with the view itself
when that from_json() accepts views but not an unrelated probe type, and
fall back to materialize() otherwise. The from_json() functions of the
NLOHMANN_DEFINE_TYPE_*, NLOHMANN_DEFINE_DERIVED_TYPE_* and
NLOHMANN_JSON_SERIALIZE_ENUM(_STRICT) macros accept basic_json values and
views; a derived type whose base reads only json reads the base part
through materialize(). The library's own from_json() overloads are not
called with views: from_json() of a view (and of the probe) only looks up
functions by ADL.

New public trait nlohmann::is_json_view<T>, and the member type
basic_json_type of basic_json_view. With duplicate keys, the members of
such a T are those the view's lookups find (the first ones).

bench_decode.cpp measures decoding into structs (4-6x faster than
materialize().get<T>() on twitter, citm_catalog, and synthetic records).

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 20:13:31 +01:00
Niels Lohmann 5a2819c940 json_view: one SIMD macro set with the library (#5921)
The view's vector code follows JSON_NO_SIMD, like the lexer and the float
writer, and skips the CPU check of SSSE3 when the code is compiled for
SSSE3 anyway (__SSSE3__), like the lexer. JSON_VIEW_NO_SIMD and
JSON_VIEW_USE_SSSE3 and their ABI tags _vns and _vssse3 are removed; they
were never released. JSON_NO_SIMD keeps its tag _ns.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 20:13:31 +01:00
Niels Lohmann 4cdfa6d0f4 json_view: no save() and load() on big-endian targets (#5920)
The image format is little-endian only. Instead of throwing
type_error.320 at runtime, save_image(), load_image() and the members
save() and load() do not exist on a big-endian target, so a call fails to
compile, like set() on a read-only document. type_error.320 remains for
saving a discarded document.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 20:13:30 +01:00
Niels Lohmann 731f1b5bfb json_view: view_mode enum instead of bool Editable, node_kind for node::kind (#5919)
* json_view: view_mode enum instead of bool Editable, node_kind for node::kind

basic_json_document and basic_json_view take a view_mode (read_only, the
default, or editable) instead of a bool: basic_json_document<json, true>
did not say what true means. The shortcut aliases are unchanged.

The kind of a node is a node_kind (the value_t values plus link, 10 as
before), which removes the static_cast<std::uint8_t>(value_t::...) of
every comparison. The node and image layouts are unchanged.

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

* json_view: node_kind in the node writers, spell out read_only, comment fixes

The builder and the edit functions take and store a node_kind instead of
casting a value_t; the numbering assertions and the comments now speak of
node_kind, and the link kind notes that it follows value_t::discarded.
The read-only aliases name view_mode::read_only like the editable ones.
view_mode.md says the mode is a compile-time property of the type.

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

* json_view: views of read-only documents convert to editable views

A read-only document has no edits, so a view of it reads correctly as a
view of an editable document before its first edit. The implicit
conversion lets a function taking a json_editable_view accept the views
of both modes. There is no conversion the other way: a read-only view of
an editable document would read wrong values after the next edit.

The mode comparisons in the cross-mode operator==/!= use an
is_other_mode trait, which astyle keeps compact.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 20:13:30 +01:00
Niels Lohmann 24078c862d docs: fix BON8 documentation gaps found in the format review (#5932)
* docs: fix BON8 documentation gaps found in the format review

Verified each claim with small C++ probes before writing it.

- index.md: BON8 serialization is also incomplete for invalid UTF-8.
- bon8.md: document duplicate keys (last wins), the error ids for
  malformed input incl. 0xF5..0xF7 + 0x80..0xBF, exact string
  termination wording, wide integers and discarded values in the
  unsupported list, and title two untitled admonitions.
- exceptions.md: to_bon8 in type_error.316, BON8 in parse_error.112
  (with example) and .113, wide integers in out_of_range.407.
- binary_values.md: bytes 0..39 take one byte in BON8.
- from_bon8.md: note on strict UTF-8 and duplicate keys.

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

* Address review of the BON8 documentation

Restore the correct statement that marker bytes cannot begin a UTF-8 character (0x80..0xBF occur in valid UTF-8 as continuation bytes), and reword two sentences.

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

* docs: drop the discarded-value remark from the BON8 page

Discarded values are not mentioned on the individual format pages.

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

* docs: do not list invalid UTF-8 strings as a BON8 serialization gap

JSON text must be valid UTF-8, and to_bon8 rejects ill-formed strings by design (type_error.316), as documented on the BON8 page. Restore the original cell and realign the table.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 18:25:46 +01:00
Niels Lohmann 60107eda3f Read BJData ND-arrays of float16, restrict ND-array char to 0..127, correct BJData docs (#5931)
* Read ND-arrays of half floats and enforce the char limit in ND-arrays

BJData N-dimensional arrays with element type 'h' (float16) failed to
read with a misleading parse_error.112, because the reader's dtype name
table lacked 'h'. It now maps to "half", the JData name. The writer still
does not pack "half"; such an object is written as a plain object and
reads back equal.

BJData limits 'C' (char) to 0..127 in Draft 2 and Draft 3, and the 1-D
reader enforces this, but ND-arrays with _ArrayType_ "char" wrote values
up to 255 as 'C' elements and read them back without a check. The writer
now only packs values in 0..127 (others fall back to a plain object that
round-trips), and the reader rejects 'C' elements above 127 with
parse_error.113 like the 1-D reader.

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

* docs: correct and complete the BJData documentation

Verify the BJData chapter against the library and the Draft 2/3/4
specifications and fix what did not match:

- bjdata.md: correct the list of unused markers (N, not Z), the ND-array
  example (3x2, not 2x3), the conditions under which an object is packed
  as an ND-array (exactly three keys, row vectors, float-only elements for
  single/double, char 0..127, byte only in Draft 3), the binary table row
  and notes (which flag/draft combinations write [$B), the "$" type
  restriction (Draft 3, Z is excluded too), the H marker in the
  deserialization table, and the claim of a complete deserialization
  mapping. Document the supported drafts, that Draft 4 (SoA containers,
  extension type E) and column-major ND-arrays are rejected, ND-arrays of
  half floats, duplicate object keys, and link the Draft 3 specifications
  instead of master.
- Add an API page for basic_json::bjdata_version_t with an example, and
  link it from the nav, the API index and to_bjdata.
- Update binary_formats/index.md and binary_values.md, which still claimed
  that BJData has no binary type, and fix a wrong byte comment there.
- Document parse_error.115 and the out_of_range.408 cases for from_bjdata,
  the precise other_error.502 condition for to_bjdata, and reword the note
  on truncated unsigned integers in exceptions.md (only ND-array elements
  were truncated before 3.13.0).

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

* Regenerate single_include and apply astyle

Result of make amalgamate (including make pretty) for the preceding changes.

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

* Address review of the BJData documentation

The $ type restriction exists since Draft 2 (Draft 3 added B), $ requires a count, ND char above 127 is rejected on read, and the new API page is listed in alphabetical order in the nav.

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

* docs: format tables, use the Oxford comma

Reformat the tables changed by this PR (BJData serialization and
deserialization mappings, completeness and binary-value tables) so all
rows are aligned, and add the Oxford comma to lists of three or more
items in the added text.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 18:25:46 +01:00
Niels Lohmann dc768a7d5d Fix BSON binary subtype 0x02 and check the declared document size earlier (#5930)
* Write and read the inner length of BSON binary subtype 0x02

The BSON specification defines the payload of the "binary (old)" subtype
0x02 as an int32 followed by that many bytes. to_bson wrote the plain
payload instead, so decoders such as pymongo and libbson-based readers
rejected the bytes, and from_bson returned the inner length as part of the
payload (documented as lenient behavior in gh-5333).

The writer now emits the outer length (payload + 4), the subtype, the inner
int32 holding the payload size, and the payload. The reader requires an
outer length of at least 4 and an inner length equal to the outer length
minus 4 (the cases the bson-corpus lists as decode errors), reports parse
error 112 otherwise, and returns only the payload. Both directions change
together so that the round trip keeps working.

The single-reservation fast path for scalar entries declines subtype 0x02
because it has no room for the inner length.

This is a deliberate exception to the opt-in rule for behavior changes:
the previous output was invalid BSON.

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

* Check the declared BSON document size before reading its content

The BSON reader compared a document's declared size with the number of bytes
read only when it reached the terminator. The declared size never bounded
the reads, so a SAX handler saw the keys and values of a document whose size
was too small before parse error 112 was reported.

The container frame now stores the position where the document ends
according to its declared size. open_bson_document rejects a size below 5
(size prefix plus terminator) and an embedded document that does not end
before the terminator of its enclosing document; the element loop rejects an
element whose type byte leaves no room for the name terminator and the
document terminator. The terminator check stays and still catches a declared
size that is too large. No input that was accepted before is rejected now;
documents with a wrong size are reported earlier, with fewer SAX events, a
different byte position and, in three cases, a different message. The error
id (parse_error.112) is unchanged and strict=false still does not skip the
check.

The tests that asserted the old messages and positions are updated, with the
outer sizes of two inputs corrected so that they still exercise the embedded
document. New tests cover the SAX events, a size below 5, and an embedded
document that fits exactly.

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

* Document BSON subtype 0x02, document size checks, and lenient reads

Describe the inner length of binary subtype 0x02 that to_bson now writes and
from_bson checks and removes. Add the document size checks (parse_error.112,
not affected by strict=false) to bson.md and from_bson.md, and extend the
list of lenient reads with the UUID and MD5 payload lengths (not checked),
duplicate keys (last value wins), embedded NUL bytes in strings, and the
ignored trailing bytes with strict=false. State that the members of an object
are written in iteration order.

Correct the statement that element names are never validated on read: they
are checked and sanitized like string values by the error handler. Add the
BSON message to the examples of out_of_range.415 and type_error.321, the
subtype limit of 255 to the binary values page, CBOR to the formats that use
byte_container_with_subtype, and fix a typo in the incomplete mapping box.

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

* Regenerate single_include and apply astyle

Result of make amalgamate (including make pretty) for the preceding changes.

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

* Address review of the BSON documentation

Describe exactly when a too small document size is detected and note that subtype 2 data written by earlier versions is not readable.

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

* docs: use the Oxford comma, drop discarded-value remarks

Add the serial comma in a list added by this PR and remove the BSON
example of type_error.321 (with the type_error.317 remark) so the docs do
not mention discarded values for BSON; restore the original singular
heading of that section. No tables were changed by this PR.

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

* Fix -Weffc++ in the BSON recorder test and a clang-tidy use-auto hit

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

* Fix clang-tidy readability-redundant-member-init in BSON test

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 18:25:46 +01:00
Niels Lohmann 0c3570d44a Validate the UBJSON/BJData container type marker for count 0; fix UBJSON docs (#5929)
* Validate the optimized-container type marker for count 0 in UBJSON and BJData

The '$' type marker of an optimized container was only checked when an
element was read, so containers with count 0 accepted any marker:
`[$x#i0`, `{$x#i0` and `[$E#i0` parsed as empty containers although a
non-empty container with the same marker is rejected and the UBJSON
specification requires a legal marker after '$'.

get_ubjson_size_type() now checks the marker right after '$' against the
allowed set (UBJSON: Z N T F i U I l L d D H C S [ {; BJData: B U i u I m
l M L h d D C, with the existing exclusion of T F Z N S H [ {) and reports
parse_error.112 "marker ... is not a permitted optimized array type".

Input that was accepted and is now rejected: an optimized container with
count 0 and an invalid '$' type marker. Valid input is unaffected. Two
existing tests that used an invalid marker incidentally ("[$#" and a
negative-count case) were adapted.

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

* Correct and complete the UBJSON documentation

Fix statements that disagree with the behavior (checked with probes):
- `Z` is null; the unused marker is `N`.
- `$` requires `#`; use_type with use_size=false throws other_error.502 only
  for non-empty arrays, objects and binary values.
- NaN and infinity are written as IEEE 754 float64 and read back unchanged;
  the UBJSON specification encodes infinity as null.
- `H` is documented (semantics, parse_error.115, out_of_range.406); the
  "complete mapping" claim is qualified.
- use_type "same type" means same marker.
- Long Z/T/F arrays lose only the `$` annotation; the `#` count and the
  element markers are kept.
- from_ubjson lists the 112, 113, 115, 406 and 408 causes that occur for
  UBJSON, without the BJData-only ND-array wording.
- Duplicate object keys keep the last value; the `$` type marker is
  validated even for count 0.
- Smaller fixes: float32 row, "map" -> "object", https link, exception 110
  strict case, to_ubjson history of discarded values.

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

* Regenerate single_include and apply astyle

Result of make amalgamate (including make pretty) for the preceding changes.

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

* Address review of the UBJSON documentation

Clarify that empty containers carry no $ annotation of their own and note that a counted N object is not supported.

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

* docs: format tables, use the Oxford comma, drop discarded-value remarks

Reformat the two UBJSON mapping tables that this PR changed (uniform column
widths, padded cells), use the serial comma in lists of three or more in the
added text, and restore the original type_error.321 bullet in to_ubjson.md.

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

* Fix narrowing of the optimized-container count in BJData and UBJSON tests

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 18:25:45 +01:00
Niels Lohmann 2bbe80c043 Document MessagePack ext types and fix related doc errors (#5928)
* Document MessagePack ext types and fix related doc errors

Add an "Extension types (ext, fixext)" section to the MessagePack page:
ext/fixext are read as binary, the signed ext type is exposed as an
unsigned subtype 0..255 (-1 reads as 255), Timestamp is not interpreted,
subtypes are always written as ext/fixext, and subtypes above 255 throw
out_of_range.415. Add the 0xC1 row to the deserialization table, note
that duplicate keys keep the last value, and correct the NaN/Infinity
explanation, the "31 bytes / 15 elements" wording, the ill-formed UTF-8
sentence, and the generic 0xC1-key error message.

Add fixext16 and the unsigned subtype mapping to binary_t.md and
binary_values.md, reword "maximum of the MessagePack ext type" in
to_msgpack.md and exceptions.md, and mark MessagePack deserialization
as incomplete (non-string keys) in the binary formats overview.

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

* Address review of the MessagePack documentation

Name parse_error.113 for a 0xC1 map key, move the duplicate-key sentence out of the ext section, and keep the 0xC1 row in marker order.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 18:25:44 +01:00
Niels Lohmann d5da84249f Skip CBOR tags in front of map keys, validate indefinite text chunks, fix CBOR docs (#5927)
* Skip CBOR tags in front of map keys and validate indefinite text chunks

A tag in front of a text string map key was rejected with parse_error.113
even with cbor_tag_handler_t::ignore or store, although tags in front of
values are handled. The tags are now skipped iteratively before the key is
read; the handler error still rejects them.

The chunks of an indefinite-length text string were concatenated before
the single UTF-8 check, so a code point split over two chunks, or an
invalid chunk, was accepted. RFC 8949, Section 3.2.3 requires every chunk
to be valid on its own. With error_handler_t::strict, replace and ignore
each chunk is now checked; keep is unchanged. The chunks are appended with
append(ptr, len), so StringType needs nothing new.

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

* docs: correct and extend the CBOR documentation

Fix the negative-integer rows (they used MessagePack boundaries), the
number_integer range of the 0x1B row, and the half-precision entry in the
list of unused types; correct the NaN history (0xF9 since 3.8.0) and the
tagged-item wording (only the tag directly in front of a byte string is
stored, and only in the 0xD8..0xDB form). Document that to_cbor is not
RFC 8949 deterministic, that duplicate keys are accepted (last wins),
tags in front of keys, per-chunk UTF-8 validation, the exceptions
parse_error.113, out_of_range.406/408 of from_cbor, the pointer and
C array input traps, the partially written output on exceptions, and the
store/ignore results in the binary values example. Drop the claim that
the CBOR reader needs StringType::append(const StringType&) and
BinaryType::insert(pos, first, last).

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

* Regenerate single_include and apply astyle

Result of make amalgamate (including make pretty) for the preceding changes.

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

* Address review of the CBOR changes

Cite RFC 8949 Section 5.3.1 for duplicate keys, describe the out_of_range.408 condition precisely, rewrap a long line, and update the stale get_string comment (per-chunk UTF-8 check). single_include regenerated.

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

* docs: drop discarded-value remarks

Remove the mention that a discarded value cannot be serialized to CBOR
(type_error.321) from the exception-safety and mapping sections. The
integer table and all added prose already follow the table-format and
Oxford-comma rules.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 18:25:44 +01:00
Niels Lohmann 81d66291c5 Create objects for pointer tokens that cannot be array indices (#5358)
* create objects for tokens that cannot be array indices (#5357)

When operator[](json_pointer) traverses a level that does not exist yet,
the null value is turned into an array or an object depending on the
reference token. The check only tested whether all characters are digits,
so tokens that can never be a valid array index selected an array and
then failed:

- "01" (and any other token with a leading '0') threw parse_error.106
- the empty token threw out_of_range.404

Both tokens are valid object keys, and both work when the level already
exists as an object, so creating the level changed the outcome. Test the
token against the RFC 6901, Sect. 4 grammar for array indices instead, so
that such tokens create an object. This only affects pointers that threw
before.

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

* Clarify that the token 0 is a valid array index in operator[] docs

The note described valid array indices as "a nonempty sequence of digits
without a leading 0", which read literally excludes the token "0" itself,
contradicting both the code and the /foo/0/0/0 example in the next
sentence. Spell out the RFC 6901 grammar instead.

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

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 17:13:48 +01:00
Niels LohmannandClaude Sonnet 5.5 c712df0637 docs: make the diff() and patch() documentation accurate; add tests (#5939)
* Throw out_of_range.411 for JSON Patch add into a null parent (#5917)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MKJf48vnGtTE25KscmjfaW
Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com>

* docs: make the diff() and patch() documentation accurate; add tests

Document the exceptions to the diff round-trip invariant (NaN, discarded
values, number types), the path parameter, non-minimal patches, array and
object operation order, the ordered_json fallback, binary values in
serialized patches, the real complexity, duplicate member names in
operations, test on missing paths, and the exact out_of_range.403 message.
Add tests for these behaviors.

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

---------

Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 17:12:05 +01:00
Niels Lohmann 7a10bf25d2 docs: state merge_patch complexity and RFC 7396 limitations; test non-object, discarded, binary cases (#5938)
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 17:11:55 +01:00
Niels Lohmann c20b6eddf4 docs: correct JSON Pointer documentation and add tests (#5937)
Fix inaccurate or missing statements about unflatten (third round-trip
failure, empty token, typo), value (type_error.306 before pointer lookup),
contains (pointer overload), parent_pointer and operator<< (bad_alloc),
out_of_range.410 example, template parameter requirements (resize(n)), and
document the URI fragment form and non-unique member names of RFC 6901.
Add tests for the unflatten and value() cases.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 17:11:46 +01:00
Niels Lohmann 8679c011db Use flawfinder --exclude instead of listing directories (#5935)
Flawfinder 2.0.20 has an --exclude PATTERN option. Scan `./` and exclude
`*/single_include/*` so that new top-level directories are covered
automatically. The scanned file set is identical to the explicit
directory list.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 17:11:36 +01:00
Niels LohmannandClaude Sonnet 5.5 d6431a9104 Throw out_of_range.411 for JSON Patch add into a null parent (#5917) (#5918)
Claude-Session: https://claude.ai/code/session_01MKJf48vnGtTE25KscmjfaW

Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 17:11:25 +01:00
518 changed files with 19211 additions and 15234 deletions

No files matched your search

+9 -2
View File
@@ -111,8 +111,6 @@ context which existing file needs to be extended, and only very few cases requir
When fixing a bug, edit `unit-regression3.cpp` and add a section referencing the fixed issue.
`unit-regression2.cpp` holds the older tests; the two files exist because a single one grew large enough for the
MinGW linker to fail relocating it, so please keep adding to the smaller file rather than growing the larger one.
Tests that call `sax_parse` go into `unit-sax_parse.cpp` rather than into a large test file: every call instantiates
the parser and the binary reader that recover from errors, which grows a test file considerably.
#### Exceptions
@@ -156,6 +154,15 @@ and each page's title (H1) and declaration by
[`docs/docset/generate_docset.py`](https://github.com/nlohmann/json/blob/develop/docs/docset/generate_docset.py);
`make build` reports API pages that cannot be classified.
A pull request that changes only the documentation, Markdown files, GitHub metadata, or license files skips the
compiler workflows (Ubuntu, macOS, Windows); the documentation and license checks still run. See
[`tools/check_path_filters`](https://github.com/nlohmann/json/tree/develop/tools/check_path_filters) for the list of
skipped files and what to do when a compiler job starts reading one of them.
Most compiler jobs run only once a maintainer adds the label "🚀 ready to merge" to a pull request; until then, a
smaller set of jobs runs on every push. See
[How CI runs](https://json.nlohmann.me/community/quality_assurance/#how-ci-runs) for the sets and when they run.
### Amalgamate the source code
The single-header files
+3 -3
View File
@@ -163,9 +163,9 @@ jobs:
python3 $GENERATOR --list-tags
TAG_COUNT=$(python3 $GENERATOR --list-tags | wc -l)
python3 $GENERATOR --abi-tags diag,_dp,_vns --abi-tags _diag --output $RUNNER_TEMP/abi_tags.natvis
grep -q '<!-- Namespace nlohmann::json_abi_diag_dp_vns -->' $RUNNER_TEMP/abi_tags.natvis
grep -q '<!-- Namespace nlohmann::json_abi_diag_dp_vns_v[0-9_]* -->' $RUNNER_TEMP/abi_tags.natvis
python3 $GENERATOR --abi-tags diag,_dp,_ns --abi-tags _diag --output $RUNNER_TEMP/abi_tags.natvis
grep -q '<!-- Namespace nlohmann::json_abi_diag_dp_ns -->' $RUNNER_TEMP/abi_tags.natvis
grep -q '<!-- Namespace nlohmann::json_abi_diag_dp_ns_v[0-9_]* -->' $RUNNER_TEMP/abi_tags.natvis
test $(grep -c '<!-- Namespace ' $RUNNER_TEMP/abi_tags.natvis) -eq $(( $(grep -c '<!-- Namespace ' nlohmann_json.natvis) + 2 ))
python3 $GENERATOR --all --output $RUNNER_TEMP/all.natvis
+2 -2
View File
@@ -43,8 +43,8 @@ jobs:
- name: flawfinder_scan
uses: david-a-wheeler/flawfinder@c4216b74cf2639ffa98503768bd6e4299b5440c9 # v2.0.20
with:
# single_include/ is omitted: it is generated from include/ and would report every finding twice
arguments: '--sarif ./cmake ./docs ./include ./src ./tests ./tools'
# single_include/ is generated from include/ and would report every finding twice
arguments: "--sarif --exclude '*/single_include/*' ./"
output: 'flawfinder_results.sarif'
- name: Upload analysis results to GitHub Security tab
+83 -6
View File
@@ -7,25 +7,60 @@ on:
- master
- release/*
pull_request:
# labeled: the "🚀 ready to merge" label starts the full set (see below)
types: [opened, synchronize, reopened, labeled]
# Skip pull requests that change only files no job here reads. The list is checked by
# tools/check_path_filters/check_path_filters.py (repository_checks.yml); change both together.
paths:
- '**'
- '!docs/**'
- '!**.md'
- '!.github/*'
- '!.github/ISSUE_TEMPLATE/**'
- '!.github/external_ci/**'
- '!.github/workflows/**'
- '!.reuse/**'
- '!LICENSES/**'
- '!CITATION.cff'
- '!REUSE.toml'
# read by tools/check_build_options in the ci_meson_install job (ubuntu.yml)
- 'docs/mkdocs/docs/integration/package_managers.md'
# built by the swiftpm job (macos.yml)
- 'docs/mkdocs/docs/integration/swift/**'
- '.github/workflows/macos.yml'
workflow_dispatch:
# A run triggered by any other label gets a group of its own, so it does not
# cancel the run of the last push; its jobs are skipped.
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
group: ${{ github.workflow }}-${{ github.event_name == 'schedule' && 'nightly' || github.ref || github.run_id }}${{ github.event.action == 'labeled' && github.event.label.name != '🚀 ready to merge' && format('-{0}', github.run_id) || '' }}
cancel-in-progress: true
permissions:
contents: read
# The jobs are split into a PR set and a full set like in ubuntu.yml (see "How
# CI runs" in docs/mkdocs/docs/community/quality_assurance.md): the PR set runs
# on every push; the full set after the PR set passed, on pushes and on pull
# requests with the "🚀 ready to merge" label. tools/ci_jobs checks that every
# job belongs to exactly one set.
jobs:
###########################################################################
# PR set
###########################################################################
macos-15:
if: &pr_set ${{ github.event_name != 'schedule' && (github.event.action != 'labeled' || github.event.label.name == '🚀 ready to merge') }}
runs-on: macos-15 # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
strategy:
matrix:
xcode: ['16.0', '16.1', '16.2', '16.3', '16.4', '26.0.1', '26.1.1', '26.2', '26.3']
xcode: ['16.0', '16.4', '26.3']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps:
steps: &xcode_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -37,10 +72,11 @@ jobs:
run: cd build ; ctest -j 10 --output-on-failure
macos-26:
if: *pr_set
runs-on: macos-26 # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md
strategy:
matrix:
xcode: ['26.4.1', '26.5', '26.6']
xcode: ['26.6']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
@@ -56,12 +92,13 @@ jobs:
run: cd build ; ctest -j 10 --output-on-failure
xcode_standards:
if: *pr_set
runs-on: macos-latest
strategy:
matrix:
standard: [11, 14, 17, 20, 23, 26]
standard: [14]
steps:
steps: &xcode_standards_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -73,6 +110,7 @@ jobs:
run: cd build ; ctest -j 10 --output-on-failure
swiftpm:
if: *pr_set
runs-on: macos-15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -106,3 +144,42 @@ jobs:
EOF
cd /tmp/json-swiftpm-consumer
swift build
###########################################################################
# full set: starts after the PR set passed
###########################################################################
macos-15_full:
needs: &pr_set_jobs [macos-15, macos-26, xcode_standards, swiftpm]
if: &full_set ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, '🚀 ready to merge') }}
runs-on: macos-15 # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
strategy:
matrix:
xcode: ['16.1', '16.2', '16.3', '26.0.1', '26.1.1', '26.2']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps: *xcode_steps
macos-26_full:
needs: *pr_set_jobs
if: *full_set
runs-on: macos-26 # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md
strategy:
matrix:
xcode: ['26.4.1', '26.5']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps: *xcode_steps
xcode_standards_full:
needs: *pr_set_jobs
if: *full_set
runs-on: macos-latest
strategy:
matrix:
standard: [11, 17, 20, 23, 26]
steps: *xcode_standards_steps
+83
View File
@@ -0,0 +1,83 @@
name: Repository checks
# Checks that concern files the compiler workflows (ubuntu.yml, macos.yml,
# windows.yml) skip with their path filter: the documentation, the license
# information, and the CI configuration itself. This workflow has no path filter.
on:
push:
branches:
- develop
- master
- release/*
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true
jobs:
check_ci_configuration:
runs-on: ubuntu-26.04
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check the path filters of the compiler workflows
run: python3 tools/check_path_filters/check_path_filters.py
- name: Check the job sets of the compiler workflows and their documentation
run: |
python3 -m venv venv
venv/bin/pip install --quiet -r tools/ci_jobs/requirements.txt
venv/bin/python tools/ci_jobs/ci_jobs.py
ci_reuse_compliance:
runs-on: ubuntu-26.04
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_reuse_compliance
ci_test_documentation:
runs-on: ubuntu-26.04
strategy:
matrix:
target: [ci_test_examples, ci_test_build_documentation, ci_test_documentation_mermaid]
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# the git-revision-date-localized plugin needs the history; a shallow clone makes the strict build fail
fetch-depth: ${{ matrix.target == 'ci_test_build_documentation' && '0' || '1' }}
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
if: matrix.target == 'ci_test_documentation_mermaid'
with:
node-version: 24
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
+422 -262
View File
@@ -7,17 +7,62 @@ on:
- master
- release/*
pull_request:
# labeled: the "🚀 ready to merge" label starts the full set (see below)
types: [opened, synchronize, reopened, labeled]
# Skip pull requests that change only files no job here reads. The list is checked by
# tools/check_path_filters/check_path_filters.py (repository_checks.yml); change both together.
paths:
- '**'
- '!docs/**'
- '!**.md'
- '!.github/*'
- '!.github/ISSUE_TEMPLATE/**'
- '!.github/external_ci/**'
- '!.github/workflows/**'
- '!.reuse/**'
- '!LICENSES/**'
- '!CITATION.cff'
- '!REUSE.toml'
# read by tools/check_build_options in the ci_meson_install job (ubuntu.yml)
- 'docs/mkdocs/docs/integration/package_managers.md'
# built by the swiftpm job (macos.yml)
- 'docs/mkdocs/docs/integration/swift/**'
- '.github/workflows/ubuntu.yml'
schedule:
# the nightly set (see below), on develop
- cron: '0 2 * * *'
workflow_dispatch:
permissions:
contents: read
# A run triggered by any other label gets a group of its own, so it does not
# cancel the run of the last push; its jobs are skipped.
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
group: ${{ github.workflow }}-${{ github.event_name == 'schedule' && 'nightly' || github.ref || github.run_id }}${{ github.event.action == 'labeled' && github.event.label.name != '🚀 ready to merge' && format('-{0}', github.run_id) || '' }}
cancel-in-progress: true
# The jobs are split into three sets (see "How CI runs" in
# docs/mkdocs/docs/community/quality_assurance.md):
#
# - PR set: every pull request push and every push; chosen because these jobs
# caught 92 % of the failing commits in Sep/Oct 2026.
# - full set: after the PR set passed, on pushes and on pull requests with the
# "🚀 ready to merge" label; every remaining compiler, version and standard.
# - nightly set: slow tools and rare compilers, nightly on develop, on pushes
# to master and release/*, and when started by hand.
#
# A matrix whose entries belong to different sets is split into one job per
# set; the jobs share their steps through YAML anchors. tools/ci_jobs checks
# that every job belongs to exactly one set.
jobs:
###########################################################################
# PR set
###########################################################################
ci_test_gcc:
if: &pr_set ${{ github.event_name != 'schedule' && (github.event.action != 'labeled' || github.event.label.name == '🚀 ready to merge') }}
runs-on: ubuntu-latest
container: gcc:latest
steps:
@@ -32,6 +77,7 @@ jobs:
run: cmake --build build --target ci_test_gcc
ci_meson_install:
if: *pr_set
runs-on: ubuntu-26.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -76,7 +122,342 @@ jobs:
cmake -S tests/cmake_import/project -B build-import-split -DCMAKE_PREFIX_PATH=${{ github.workspace }}/install-split
cmake --build build-import-split
ci_static_analysis_ubuntu:
if: *pr_set
runs-on: ubuntu-26.04
strategy:
matrix:
target: [ci_cpplint]
steps: &static_analysis_ubuntu_steps
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- name: Install Valgrind
if: matrix.target == 'ci_test_valgrind'
run: sudo apt-get update ; sudo apt-get install -y valgrind
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
ci_static_analysis_clang:
if: *pr_set
runs-on: ubuntu-latest
container: silkeh/clang:22
strategy:
matrix:
target: [ci_test_clang, ci_clang_tidy, ci_test_clang_sanitizer, ci_single_binaries]
steps: &static_analysis_clang_steps
- name: Install git, clang-tools, iwyu (ci_single_binaries), and unzip
run: apt-get update ; apt-get install -y git clang-tools iwyu unzip
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
ci_cmake_options:
if: *pr_set
runs-on: ubuntu-latest
container: ubuntu:24.04
strategy:
matrix:
target: [ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noglobaludls]
steps: &cmake_options_steps
- name: Install build-essential
run: apt-get update ; apt-get install -y build-essential unzip wget git
# the CMake 3.5.0 release binary that ci_cmake_flags downloads links
# against libidn.so.11, which Ubuntu 24.04 no longer ships
- name: Install libidn11 for CMake 3.5.0
if: matrix.target == 'ci_cmake_flags'
run: |
wget -q http://archive.ubuntu.com/ubuntu/pool/main/libi/libidn/libidn11_1.33-2.2ubuntu2_amd64.deb
dpkg -i libidn11_1.33-2.2ubuntu2_amd64.deb
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
ci_test_compilers_gcc_old:
if: *pr_set
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['4.8']
# 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: &compilers_gcc_old_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 resolves the PPA through the Launchpad API,
# which intermittently times out or fails the team lookup (the plain
# "deb ..." sources below never hit Launchpad and never flake).
# Retry with backoff so a transient Launchpad blip does not fail CI.
for attempt in 1 2 3 4 5; do
add-apt-repository -y ppa:ubuntu-toolchain-r/test && break
echo "::warning::add-apt-repository ppa:ubuntu-toolchain-r/test failed (attempt ${attempt}/5); retrying"
sleep $((attempt * 10))
done
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_g++-${{ matrix.compiler }}
ci_test_compilers_clang:
if: *pr_set
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['3.4']
container: silkeh/clang:${{ matrix.compiler }}
steps: &compilers_clang_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Disable filesystem support (std::filesystem is unusable) for clang 7 / 8 / 9 / 10
run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV"
if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }}
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_default
ci_test_standards_gcc:
if: *pr_set
runs-on: ubuntu-latest
container: gcc:latest
strategy:
matrix:
standard: [26]
steps: &standards_gcc_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_gcc_cxx${{ matrix.standard }}
ci_test_standards_clang:
if: *pr_set
runs-on: ubuntu-latest
container: silkeh/clang:latest
strategy:
matrix:
standard: [26]
stdlib: [libcxx]
steps: &standards_clang_steps
- name: Install git and unzip
run: apt-get update ; apt-get install -y git unzip
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build with libc++
run: cmake --build build --target ci_test_clang_libcxx_cxx${{ matrix.standard }}
if: ${{ matrix.stdlib == 'libcxx' }}
- name: Build with libstdc++
run: cmake --build build --target ci_test_clang_cxx${{ matrix.standard }}
if: ${{ matrix.stdlib == 'libstdcxx' }}
ci_emscripten:
if: *pr_set
runs-on: ubuntu-26.04
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- name: Install emscripten
uses: mymindstorm/setup-emsdk@4528d102f7230f0e7b276855c01ea1159be0e984 # v16
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja
- name: Build
run: cmake --build build
###########################################################################
# full set: starts after the PR set passed
###########################################################################
ci_static_analysis_ubuntu_full:
needs: &pr_set_jobs [ci_test_gcc, ci_meson_install, ci_static_analysis_ubuntu, ci_static_analysis_clang, ci_cmake_options, ci_test_compilers_gcc_old, ci_test_compilers_clang, ci_test_standards_gcc, ci_test_standards_clang, ci_emscripten]
if: &full_set ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, '🚀 ready to merge') }}
runs-on: ubuntu-26.04
strategy:
matrix:
target: [ci_test_single_header, ci_cppcheck, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata]
steps: *static_analysis_ubuntu_steps
ci_static_analysis_clang_full:
needs: *pr_set_jobs
if: *full_set
runs-on: ubuntu-latest
container: silkeh/clang:22
strategy:
matrix:
target: [ci_clang_analyze]
steps: *static_analysis_clang_steps
ci_cmake_options_full:
needs: *pr_set_jobs
if: *full_set
runs-on: ubuntu-latest
container: ubuntu:24.04
strategy:
matrix:
target: [ci_cmake_flags, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_delete_deprecated_functions, ci_test_no_thread_local]
steps: *cmake_options_steps
ci_test_compilers_gcc_old_full:
needs: *pr_set_jobs
if: *full_set
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['4.9', '5', '6']
container: ubuntu:20.04
steps: *compilers_gcc_old_steps
ci_test_compilers_gcc_full:
needs: *pr_set_jobs
if: *full_set
runs-on: ubuntu-latest
strategy:
matrix:
# older GCC docker images (4, 5, 6) fail to check out code
compiler: ['7', '8', '9', '10', '11', '12', '13', '14', '15', '16', 'latest']
container: gcc:${{ matrix.compiler }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_default
ci_test_compilers_clang_full:
needs: *pr_set_jobs
if: *full_set
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['3.5', '3.6', '3.7', '3.8', '3.9', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15-bullseye', '16', '17', '18', '19', '20', '21', '22', 'latest']
container: silkeh/clang:${{ matrix.compiler }}
steps: *compilers_clang_steps
ci_test_standards_gcc_full:
needs: *pr_set_jobs
if: *full_set
runs-on: ubuntu-latest
container: gcc:latest
strategy:
matrix:
standard: [11, 14, 17, 20, 23]
steps: *standards_gcc_steps
ci_test_standards_clang_full:
needs: *pr_set_jobs
if: *full_set
runs-on: ubuntu-latest
container: silkeh/clang:latest
strategy:
matrix:
standard: [11, 14, 17, 20, 23, 26]
stdlib: [libcxx, libstdcxx]
exclude:
# in the PR set
- standard: 26
stdlib: libcxx
steps: *standards_clang_steps
ci_module_cpp20:
needs: *pr_set_jobs
if: *full_set
strategy:
matrix:
container: ['gcc:latest', 'silkeh/clang:latest']
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# The module test uses `import std;`, which needs CMake's experimental
# import-std support. Its opt-in token is CMake-version-specific, so pin
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt.
- name: Get pinned CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
with:
cmakeVersion: 4.3.4
# Clang: the std library module is provided by libc++ (the image's libstdc++
# ships none), and the image's libc++ module manifest has a broken relative
# path — repoint it at the real module sources.
- name: Use libc++ and fix its module manifest path (Clang)
if: matrix.container == 'silkeh/clang:latest'
run: |
echo "CXXFLAGS=-stdlib=libc++" >> "$GITHUB_ENV"
mkdir -p /usr/lib/share && ln -sf /usr/lib/llvm-*/share/libc++ /usr/lib/share/libc++
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_module_cpp20
###########################################################################
# nightly set
###########################################################################
ci_infer:
if: &nightly_set ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref != 'refs/heads/develop') }}
runs-on: ubuntu-26.04
steps:
- name: Harden Runner
@@ -105,76 +486,16 @@ jobs:
path: ${{ github.workspace }}/build/build_infer/infer-out/report.txt
if-no-files-found: ignore
ci_static_analysis_ubuntu:
ci_static_analysis_ubuntu_nightly:
if: *nightly_set
runs-on: ubuntu-26.04
strategy:
matrix:
target: [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@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- name: Install Valgrind
if: matrix.target == 'ci_test_valgrind'
run: sudo apt-get update ; sudo apt-get install -y valgrind
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
ci_static_analysis_clang:
runs-on: ubuntu-latest
container: silkeh/clang:22
strategy:
matrix:
target: [ci_test_clang, ci_clang_tidy, ci_test_clang_sanitizer, ci_clang_analyze, ci_single_binaries]
steps:
- name: Install git, clang-tools, iwyu (ci_single_binaries), and unzip
run: apt-get update ; apt-get install -y git clang-tools iwyu unzip
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
ci_cmake_options:
runs-on: ubuntu-latest
container: ubuntu:24.04
strategy:
matrix:
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_delete_deprecated_functions, ci_test_no_thread_local]
steps:
- name: Install build-essential
run: apt-get update ; apt-get install -y build-essential unzip wget git
# the CMake 3.5.0 release binary that ci_cmake_flags downloads links
# against libidn.so.11, which Ubuntu 24.04 no longer ships
- name: Install libidn11 for CMake 3.5.0
if: matrix.target == 'ci_cmake_flags'
run: |
wget -q http://archive.ubuntu.com/ubuntu/pool/main/libi/libidn/libidn11_1.33-2.2ubuntu2_amd64.deb
dpkg -i libidn11_1.33-2.2ubuntu2_amd64.deb
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
target: [ci_test_valgrind]
steps: *static_analysis_ubuntu_steps
ci_test_coverage:
if: *nightly_set
runs-on: ubuntu-26.04
steps:
- name: Harden Runner
@@ -208,128 +529,8 @@ jobs:
path-to-lcov: ${{ github.workspace }}/build/json.info.filtered.noexcept
fail-on-error: false
ci_test_compilers_gcc_old:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['4.8', '4.9', '5', '6']
# 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 resolves the PPA through the Launchpad API,
# which intermittently times out or fails the team lookup (the plain
# "deb ..." sources below never hit Launchpad and never flake).
# Retry with backoff so a transient Launchpad blip does not fail CI.
for attempt in 1 2 3 4 5; do
add-apt-repository -y ppa:ubuntu-toolchain-r/test && break
echo "::warning::add-apt-repository ppa:ubuntu-toolchain-r/test failed (attempt ${attempt}/5); retrying"
sleep $((attempt * 10))
done
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_g++-${{ matrix.compiler }}
ci_test_compilers_gcc:
runs-on: ubuntu-latest
strategy:
matrix:
# older GCC docker images (4, 5, 6) fail to check out code
compiler: ['7', '8', '9', '10', '11', '12', '13', '14', '15', '16', 'latest']
container: gcc:${{ matrix.compiler }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_default
ci_test_compilers_clang:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['3.4', '3.5', '3.6', '3.7', '3.8', '3.9', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15-bullseye', '16', '17', '18', '19', '20', '21', '22', 'latest']
container: silkeh/clang:${{ matrix.compiler }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Disable filesystem support (std::filesystem is unusable) for clang 7 / 8 / 9 / 10
run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV"
if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }}
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_default
ci_test_standards_gcc:
runs-on: ubuntu-latest
container: gcc:latest
strategy:
matrix:
standard: [11, 14, 17, 20, 23, 26]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_gcc_cxx${{ matrix.standard }}
ci_test_standards_clang:
runs-on: ubuntu-latest
container: silkeh/clang:latest
strategy:
matrix:
standard: [11, 14, 17, 20, 23, 26]
stdlib: [libcxx, libstdcxx]
steps:
- name: Install git and unzip
run: apt-get update ; apt-get install -y git unzip
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build with libc++
run: cmake --build build --target ci_test_clang_libcxx_cxx${{ matrix.standard }}
if: ${{ matrix.stdlib == 'libcxx' }}
- name: Build with libstdc++
run: cmake --build build --target ci_test_clang_cxx${{ matrix.standard }}
if: ${{ matrix.stdlib == 'libstdcxx' }}
ci_cuda_example:
if: *nightly_set
runs-on: ubuntu-latest
strategy:
fail-fast: false
@@ -352,37 +553,8 @@ jobs:
- name: Build
run: cmake --build build --target ci_cuda_example
ci_module_cpp20:
strategy:
matrix:
container: ['gcc:latest', 'silkeh/clang:latest']
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# The module test uses `import std;`, which needs CMake's experimental
# import-std support. Its opt-in token is CMake-version-specific, so pin
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt.
- name: Get pinned CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
with:
cmakeVersion: 4.3.4
# Clang: the std library module is provided by libc++ (the image's libstdc++
# ships none), and the image's libc++ module manifest has a broken relative
# path — repoint it at the real module sources.
- name: Use libc++ and fix its module manifest path (Clang)
if: matrix.container == 'silkeh/clang:latest'
run: |
echo "CXXFLAGS=-stdlib=libc++" >> "$GITHUB_ENV"
mkdir -p /usr/lib/share && ln -sf /usr/lib/llvm-*/share/libc++ /usr/lib/share/libc++
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_module_cpp20
ci_icpc:
if: *nightly_set
runs-on: ubuntu-latest
# Intel discontinued the classic icc/icpc compiler in oneAPI 2024.0; this is
# Intel's own last officially published image that still includes it.
@@ -402,6 +574,7 @@ jobs:
run: cmake --build build --target ci_icpc
ci_icpx:
if: *nightly_set
runs-on: ubuntu-latest
container: intel/oneapi-hpckit:latest
steps:
@@ -416,6 +589,7 @@ jobs:
run: cmake --build build --target ci_icpx
ci_nvhpc:
if: *nightly_set
runs-on: ubuntu-latest
container: nvcr.io/nvidia/nvhpc:25.5-devel-cuda12.9-ubuntu22.04
steps:
@@ -429,54 +603,10 @@ jobs:
- name: Build
run: cmake --build build --target ci_nvhpc
ci_emscripten:
runs-on: ubuntu-26.04
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- name: Install emscripten
uses: mymindstorm/setup-emsdk@4528d102f7230f0e7b276855c01ea1159be0e984 # v16
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
- name: Run CMake
run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja
- name: Build
run: cmake --build build
ci_test_documentation:
runs-on: ubuntu-26.04
strategy:
matrix:
target: [ci_test_examples, ci_test_build_documentation, ci_test_documentation_mermaid]
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# the git-revision-date-localized plugin needs the history; a shallow clone makes the strict build fail
fetch-depth: ${{ matrix.target == 'ci_test_build_documentation' && '0' || '1' }}
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
if: matrix.target == 'ci_test_documentation_mermaid'
with:
node-version: 24
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
# Native Linux ARM64 runner with the latest GCC. The ubuntu-24.04-arm label is
# only available for public repositories.
ci_test_arm64:
if: *nightly_set
runs-on: ubuntu-24.04-arm
container: gcc:latest
steps:
@@ -491,3 +621,33 @@ jobs:
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_default
# A failure of a scheduled run opens an issue, or comments on the open one.
nightly_report:
needs: [ci_infer, ci_static_analysis_ubuntu_nightly, ci_test_coverage, ci_cuda_example, ci_icpc, ci_icpx, ci_nvhpc, ci_test_arm64]
if: ${{ always() && github.event_name == 'schedule' && contains(needs.*.result, 'failure') }}
runs-on: ubuntu-26.04
permissions:
issues: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- name: Open or update the nightly failure issue
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
WORKFLOW: ${{ github.workflow }}
SHA: ${{ github.sha }}
run: |
title="Nightly CI failure (${WORKFLOW})"
body="The nightly run of ${WORKFLOW} on ${SHA:0:10} failed: ${RUN_URL}"
number=$(gh issue list --state open --search "in:title \"${title}\"" --json number,title --jq "map(select(.title == \"${title}\")) | .[0].number // empty")
if [ -n "$number" ]; then
gh issue comment "$number" --body "$body"
else
gh issue create --title "$title" --body "$body"
fi
+215 -33
View File
@@ -7,23 +7,62 @@ on:
- master
- release/*
pull_request:
# labeled: the "🚀 ready to merge" label starts the full set (see below)
types: [opened, synchronize, reopened, labeled]
# Skip pull requests that change only files no job here reads. The list is checked by
# tools/check_path_filters/check_path_filters.py (repository_checks.yml); change both together.
paths:
- '**'
- '!docs/**'
- '!**.md'
- '!.github/*'
- '!.github/ISSUE_TEMPLATE/**'
- '!.github/external_ci/**'
- '!.github/workflows/**'
- '!.reuse/**'
- '!LICENSES/**'
- '!CITATION.cff'
- '!REUSE.toml'
# read by tools/check_build_options in the ci_meson_install job (ubuntu.yml)
- 'docs/mkdocs/docs/integration/package_managers.md'
# built by the swiftpm job (macos.yml)
- 'docs/mkdocs/docs/integration/swift/**'
- '.github/workflows/windows.yml'
schedule:
# the nightly set (see below), on develop
- cron: '0 2 * * *'
workflow_dispatch:
permissions:
contents: read
# A run triggered by any other label gets a group of its own, so it does not
# cancel the run of the last push; its jobs are skipped.
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
group: ${{ github.workflow }}-${{ github.event_name == 'schedule' && 'nightly' || github.ref || github.run_id }}${{ github.event.action == 'labeled' && github.event.label.name != '🚀 ready to merge' && format('-{0}', github.run_id) || '' }}
cancel-in-progress: true
# The jobs are split into three sets like in ubuntu.yml (see "How CI runs" in
# docs/mkdocs/docs/community/quality_assurance.md): the PR set runs on every
# push; the full set after the PR set passed, on pushes and on pull requests
# with the "🚀 ready to merge" label; the nightly set nightly on develop, on
# pushes to master and release/*, and when started by hand. tools/ci_jobs
# checks that every job belongs to exactly one set.
jobs:
###########################################################################
# PR set
###########################################################################
mingw:
if: &pr_set ${{ github.event_name != 'schedule' && (github.event.action != 'labeled' || github.event.label.name == '🚀 ready to merge') }}
runs-on: windows-2022
strategy:
matrix:
architecture: [x64, x86]
architecture: [x86]
steps:
steps: &mingw_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -40,15 +79,26 @@ jobs:
run: cd build ; ctest -j 10 -C Debug --output-on-failure
msvc:
if: *pr_set
strategy:
matrix:
build_type: [Debug, Release]
architecture: [Win32, x64]
std_version: [default, latest]
include:
- build_type: Debug
architecture: x64
std_version: default
- build_type: Release
architecture: x64
std_version: default
- build_type: Debug
architecture: Win32
std_version: default
- build_type: Release
architecture: Win32
std_version: latest
runs-on: windows-2022
steps:
steps: &msvc_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -77,15 +127,20 @@ jobs:
# Visual Studio 2026 (v145 toolset) on the windows-2025 image. The "Visual Studio
# 18 2026" generator requires CMake 4.2+, so a recent CMake is fetched explicitly.
msvc-vs2026:
if: *pr_set
strategy:
matrix:
build_type: [Debug, Release]
architecture: [Win32, x64]
std_version: [default, latest]
include:
- build_type: Debug
architecture: x64
std_version: latest
- build_type: Release
architecture: Win32
std_version: default
runs-on: windows-2025
steps:
steps: &msvc_vs2026_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -117,13 +172,14 @@ jobs:
# Native ARM64 Windows runner with the MSVC ARM64 toolset. The windows-11-arm
# label is only available for public repositories.
msvc-arm64:
if: *pr_set
strategy:
matrix:
build_type: [Debug, Release]
build_type: [Debug]
runs-on: windows-11-arm
steps:
steps: &msvc_arm64_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -141,12 +197,13 @@ jobs:
run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure
clang:
if: *pr_set
runs-on: windows-2022
strategy:
matrix:
version: [11.0.1, 12.0.1, 13.0.1, 14.0.6, 15.0.7, 16.0.6, 18.1.8, 19.1.7, 20.1.8]
version: [20.1.8]
steps:
steps: &clang_steps
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -189,24 +246,8 @@ jobs:
- name: Test
run: cd build ; ctest -j 10 -C Debug --output-on-failure
clang-cl:
runs-on: windows-2022
strategy:
matrix:
architecture: [Win32, x64]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run CMake
run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -T ClangCL -DJSON_BuildTests=On
- name: Build
run: cmake --build build --config Debug --parallel 10
- name: Test
run: cd build ; ctest -j 10 -C Debug --output-on-failure
ci_module_cpp20:
if: *pr_set
runs-on: windows-2022
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -225,4 +266,145 @@ jobs:
run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_CI=ON -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /EHsc /W4 /WX"
- name: Build
run: cmake --build build --config Debug --target ci_module_cpp20
###########################################################################
# full set: starts after the PR set passed
###########################################################################
msvc_full:
needs: &pr_set_jobs [mingw, msvc, msvc-vs2026, msvc-arm64, clang, ci_module_cpp20]
if: &full_set ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, '🚀 ready to merge') }}
strategy:
matrix:
build_type: [Debug, Release]
architecture: [Win32, x64]
std_version: [default, latest]
exclude:
# in the PR set
- build_type: Debug
architecture: x64
std_version: default
- build_type: Release
architecture: x64
std_version: default
- build_type: Debug
architecture: Win32
std_version: default
- build_type: Release
architecture: Win32
std_version: latest
runs-on: windows-2022
steps: *msvc_steps
# Visual Studio 2026 (v145 toolset) on the windows-2025 image. The "Visual Studio
# 18 2026" generator requires CMake 4.2+, so a recent CMake is fetched explicitly.
msvc-vs2026_full:
needs: *pr_set_jobs
if: *full_set
strategy:
matrix:
build_type: [Debug, Release]
architecture: [Win32, x64]
std_version: [default, latest]
exclude:
# in the PR set
- build_type: Debug
architecture: x64
std_version: latest
- build_type: Release
architecture: Win32
std_version: default
runs-on: windows-2025
steps: *msvc_vs2026_steps
# Native ARM64 Windows runner with the MSVC ARM64 toolset. The windows-11-arm
# label is only available for public repositories.
msvc-arm64_full:
needs: *pr_set_jobs
if: *full_set
strategy:
matrix:
build_type: [Release]
runs-on: windows-11-arm
steps: *msvc_arm64_steps
clang_full:
needs: *pr_set_jobs
if: *full_set
runs-on: windows-2022
strategy:
matrix:
version: [11.0.1, 12.0.1, 13.0.1, 14.0.6, 15.0.7, 16.0.6, 18.1.8, 19.1.7]
steps: *clang_steps
clang-cl_full:
needs: *pr_set_jobs
if: *full_set
runs-on: windows-2022
strategy:
matrix:
architecture: [Win32, x64]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run CMake
run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -T ClangCL -DJSON_BuildTests=On
- name: Build
run: cmake --build build --config Debug --parallel 10
- name: Test
run: cd build ; ctest -j 10 -C Debug --output-on-failure
###########################################################################
# nightly set
###########################################################################
mingw_nightly:
if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref != 'refs/heads/develop') }}
runs-on: windows-2022
strategy:
matrix:
architecture: [x64]
steps: *mingw_steps
# A failure of a scheduled run opens an issue, or comments on the open one.
nightly_report:
needs: [mingw_nightly]
if: ${{ always() && github.event_name == 'schedule' && contains(needs.*.result, 'failure') }}
runs-on: ubuntu-26.04
permissions:
issues: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- name: Open or update the nightly failure issue
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
WORKFLOW: ${{ github.workflow }}
SHA: ${{ github.sha }}
run: |
title="Nightly CI failure (${WORKFLOW})"
body="The nightly run of ${WORKFLOW} on ${SHA:0:10} failed: ${RUN_URL}"
number=$(gh issue list --state open --search "in:title \"${title}\"" --json number,title --jq "map(select(.title == \"${title}\")) | .[0].number // empty")
if [ -n "$number" ]; then
gh issue comment "$number" --body "$body"
else
gh issue create --title "$title" --body "$body"
fi
+1
View File
@@ -90,6 +90,7 @@ cc_library(
"include/nlohmann/detail/view/simd.hpp",
"include/nlohmann/detail/view/string_ref.hpp",
"include/nlohmann/detail/view/value.hpp",
"include/nlohmann/detail/view/view_mode.hpp",
"include/nlohmann/json.hpp",
"include/nlohmann/json_fwd.hpp",
"include/nlohmann/json_literals.hpp",
+1 -1
View File
@@ -309,7 +309,7 @@ The "Check amalgamation" workflow fails if the file is out of date.
The file covers the namespace variants with up to two ABI tags. A Natvis file for other configurations can be
generated with the `--abi-tags` or `--all` options, for example
`make natvis NATVIS_ARGS="--abi-tags _diag,_dp,_vns --output my_nlohmann_json.natvis"`; see
`make natvis NATVIS_ARGS="--abi-tags _diag,_dp,_ns --output my_nlohmann_json.natvis"`; see
[`tools/generate_natvis`](tools/generate_natvis/README.md). With MSVC, CMake adds the file to the `nlohmann_json`
target and installs it.
+1 -1
View File
@@ -120,7 +120,7 @@ $(AMALGAMATED_VIEW_FILE): $(SRCS)
tools/amalgamate/amalgamate.py -c tools/amalgamate/config_json_view.json -s . --verbose=yes
NATVIS_VENV=tools/generate_natvis/venv
# extra options for generate_natvis.py, e.g. NATVIS_ARGS="--abi-tags _diag,_dp,_vns --output my.natvis"
# extra options for generate_natvis.py, e.g. NATVIS_ARGS="--abi-tags _diag,_dp,_ns --output my.natvis"
NATVIS_ARGS=
# regenerate nlohmann_json.natvis from the ABI tags and version in include/nlohmann/detail/abi_macros.hpp
+2 -2
View File
@@ -495,7 +495,7 @@ bool key(string_t& val);
bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex);
```
The return value of each function determines whether parsing should proceed. For `parse_error`, returning `true` [recovers from the error](https://json.nlohmann.me/features/parsing/error_recovery/): the parser repairs the input and continues.
The return value of each function determines whether parsing should proceed.
To implement your own SAX handler, proceed as follows:
@@ -503,7 +503,7 @@ To implement your own SAX handler, proceed as follows:
2. Create an object of your SAX interface class, e.g. `my_sax`.
3. Call `bool json::sax_parse(input, &my_sax)`; where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface.
Note the `sax_parse` function only returns a `bool` indicating whether the input was parsed without errors and no SAX event returned `false`. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error -- it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp).
Note the `sax_parse` function only returns a `bool` indicating the result of the last executed SAX event. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error -- it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp).
### STL-like access
@@ -30,7 +30,7 @@ class (either explicitly or via the conversion operators).
## Return value
1. (none) -- the converted value is written to the output parameter `val`.
1. (none) — the converted value is written to the output parameter `val`.
2. the JSON value `j` converted to `TargetType`
## Examples
@@ -67,7 +67,9 @@ class (either explicitly or via the conversion operators).
## See also
- [to_json](to_json.md)
- [`to_json`](to_json.md) - convert a C++ value to JSON
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) - write your own `from_json` and `to_json` functions
- [Converting values](../../features/conversions.md) - overview of `get`, `get_to` and implicit conversions
## Version history
+4 -4
View File
@@ -33,10 +33,10 @@ struct adl_serializer {
## See also
- [Arbitrary type conversions](../../features/arbitrary_types.md) - how to make your types convertible
- [**get**](../basic_json/get.md) / [**get_to**](../basic_json/get_to.md) - convert a JSON value to a C++ type
- [**basic_json**](../basic_json/basic_json.md) - construct a JSON value from a C++ value
- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE**](../macros/nlohmann_define_type_intrusive.md) - generate the conversion functions for a type
- [Specializing enum conversion](../../features/enum_conversion.md)
- [`get`](../basic_json/get.md) - / [`get_to`](../basic_json/get_to.md) - convert a JSON value to a C++ type
- [`basic_json`](../basic_json/basic_json.md) - construct a JSON value from a C++ value
- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](../macros/nlohmann_define_type_intrusive.md) - generate the conversion functions for a type
- [Specializing enum conversion](../../features/enum_conversion.md) - serializing enums as JSON strings
## Version history
@@ -36,7 +36,9 @@ This function is usually called by the constructors of the [basic_json](../basic
## See also
- [from_json](from_json.md)
- [`from_json`](from_json.md) - convert JSON to a C++ value
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) - write your own `from_json` and `to_json` functions
- [Converting values](../../features/conversions.md) - overview of `get`, `get_to` and implicit conversions
## Version history
+8 -3
View File
@@ -148,15 +148,20 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
## See also
- [parse](parse.md) - deserialize from a compatible input
- [sax_parse](sax_parse.md) - parse input using the SAX interface
- [operator>>](../operator_gtgt.md) - deserialize from stream
- [`parse`](parse.md) - deserialize from a compatible input
- [`sax_parse`](sax_parse.md) - parse input using the SAX interface
- [`operator>>`](../operator_gtgt.md) - deserialize from stream
- [`JSON_STRICT_NUL_HANDLING`](../macros/json_strict_nul_handling.md) - opt in to rejecting a NUL byte in the input
instead of treating it as end of input
- [`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md) - read a `std::istream` one character
at a time
- [`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md) - read a `FILE*` with the locking stdio
functions
- [Parsing](../../features/parsing/index.md) - overview of the parsing functions
- [Comments](../../features/comments.md) - ignore `//` and `/* */` comments while parsing
- [Trailing Commas](../../features/trailing_commas.md) - accept trailing commas in arrays and objects
- [Parsing and Exceptions](../../features/parsing/parse_exceptions.md) - handling parse errors and locating them in the input
- [Parsing Untrusted Input](../../features/parsing/untrusted_input.md) - limits and checks for input you do not control
## Version history
+2 -2
View File
@@ -29,9 +29,9 @@ Linear in the size of `init`.
This function is only needed to express two edge cases that cannot be realized with the initializer list constructor
([`basic_json(initializer_list_t, bool, value_t)`](basic_json.md)). These cases are:
1. creating an array whose elements are all pairs whose first element is a string -- in this case, the initializer list
1. creating an array whose elements are all pairs whose first element is a string — in this case, the initializer list
constructor would create an object, taking the first elements as keys
2. creating an empty array -- passing the empty initializer list to the initializer list constructor yields an empty
2. creating an empty array — passing the empty initializer list to the initializer list constructor yields an empty
object
## Examples
+6 -4
View File
@@ -69,10 +69,12 @@ Arrays are stored as pointers in a `basic_json` type. That is, for any access to
## See also
- [object_t](object_t.md) the type used to store JSON objects
- [binary_t](binary_t.md) the type used to store binary values
- [is_array](is_array.md) checks whether the JSON value is an array
- [max_size](max_size.md) returns the maximum possible number of elements
- [`object_t`](object_t.md) - the type used to store JSON objects
- [`binary_t`](binary_t.md) - the type used to store binary values
- [`is_array`](is_array.md) - checks whether the JSON value is an array
- [`max_size`](max_size.md) - returns the maximum possible number of elements
- [Types](../../features/types/index.md) - how arrays are stored
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the `ArrayType` template parameter
## Version history
@@ -46,7 +46,8 @@ The function is equivalent to `static_cast<json_base_class_t&>(j)` (or `static_c
## See also
- [json_base_class_t](json_base_class_t.md) - type of the custom base class
- [`json_base_class_t`](json_base_class_t.md) - type of the custom base class
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the `CustomBaseClass` template parameter
## Version history
+8 -5
View File
@@ -90,7 +90,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
1. Constant.
2. Logarithmic in the size of the container.
3. Logarithmic in the size of the container.
4. Logarithmic in the size of the container.
4. Linear in the number of reference tokens of `ptr`; for each of them, logarithmic in the size of the object, or
constant for an array.
## Notes
@@ -230,10 +231,12 @@ Strong exception safety: if an exception occurs, the original value stays intact
## See also
- documentation on [checked access](../../features/element_access/checked_access.md)
- [`operator[]`](operator%5B%5D.md) for unchecked access by reference
- [`value`](value.md) for access with default value
- [basic_json_view::at](../basic_json_view/at.md) - the same access on a zero-copy view
- [Checked access](../../features/element_access/checked_access.md) - element access with range checking
- [`operator[]`](operator%5B%5D.md) - unchecked access by reference
- [`value`](value.md) - access with default value
- [`basic_json_view::at`](../basic_json_view/at.md) - the same access on a zero-copy view
- [Element Access](../../features/element_access/index.md) - overview of all ways to access elements
- [JSON Pointer](../../features/json_pointer.md) - access nested values with a pointer
## Version history
+3 -2
View File
@@ -57,8 +57,9 @@ Constant.
## See also
- [front](front.md) to access the first element
- [basic_json_view::back](../basic_json_view/back.md) - the same access on a zero-copy view
- [`front`](front.md) - to access the first element
- [`basic_json_view::back`](../basic_json_view/back.md) - the same access on a zero-copy view
- [Element Access](../../features/element_access/index.md) - overview of all ways to access elements
## Version history
+14 -10
View File
@@ -52,7 +52,7 @@ basic_json(basic_json&& other) noexcept;
The postcondition of this constructor can be restored by calling [`clear()`](clear.md).
2. Create a `#!json null` JSON value. It either takes a null pointer as parameter (explicitly creating `#!json null`)
or no parameter (implicitly creating `#!json null`). The passed null pointer itself is not read -- it is only used to
or no parameter (implicitly creating `#!json null`). The passed null pointer itself is not read — it is only used to
choose the right constructor.
3. This is a "catch all" constructor for all compatible JSON types; that is, types for which a `to_json()` method
@@ -113,19 +113,22 @@ basic_json(basic_json&& other) noexcept;
```mermaid
flowchart TD
A(["initializer_list init"]) --> B{"empty, or every element is a 2-element<br/>array whose first element is a string?"}
B -->|"yes"| C{"type_deduction"}
B -->|"no"| D{"type_deduction"}
A(["initializer_list init"]) --> B{{"empty, or every element is a 2-element<br/>array whose first element is a string?"}}
B -->|"yes"| C{{"type_deduction"}}
B -->|"no"| D{{"type_deduction"}}
C -->|"true"| OBJ["create object"]
C -->|"false"| E{"manual_type"}
C -->|"false"| E{{"manual_type"}}
E -->|"object"| OBJ
E -->|"array"| ARR["create array"]
D -->|"true"| ARR
D -->|"false"| F{"manual_type"}
D -->|"false"| F{{"manual_type"}}
F -->|"array"| ARR
F -->|"object"| ERR["throw type_error.301"]
```
<p class="nj-caption" markdown>Decision flow for an initializer list: hexagons are checks, edge labels are their
outcomes, and rectangles are the resulting value or exception.</p>
The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows:
1. The empty initializer list is written as `#!cpp {}` which is exactly an empty JSON object.
@@ -473,12 +476,13 @@ basic_json(basic_json&& other) noexcept;
## See also
- [array](array.md) create a JSON array value, forcing array creation from an initializer list even when it looks like
- [`array`](array.md) - create a JSON array value, forcing array creation from an initializer list even when it looks like
an object
- [object](object.md) create a JSON object value, forcing object creation from an initializer list
- [binary](binary.md) create a JSON binary array value
- [operator=](operator=.md) copy assignment operator
- [`object`](object.md) - create a JSON object value, forcing object creation from an initializer list
- [`binary`](binary.md) - create a JSON binary array value
- [`operator=`](operator=.md) - copy assignment operator
- [Creating JSON values](../../features/creating_values.md) - the article on creating JSON values
- [Converting values](../../features/conversions.md) - which C++ types can be converted
## Version history
+11 -6
View File
@@ -7,7 +7,12 @@ const_iterator begin() const noexcept;
Returns an iterator to the first element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`begin()` points to the first element and `end()` to the position after the last element;
the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
@@ -39,12 +44,12 @@ Constant.
## See also
- [end](end.md) returns an iterator to one past the last element
- [cbegin](cbegin.md) returns a const iterator to the first element
- [rbegin](rbegin.md) returns a reverse iterator to the last element
- [items](items.md) returns an iteration proxy to access keys and values during range-based for loops
- [`end`](end.md) - returns an iterator to one past the last element
- [`cbegin`](cbegin.md) - returns a const iterator to the first element
- [`rbegin`](rbegin.md) - returns a reverse iterator to the last element
- [`items`](items.md) - returns an iteration proxy to access keys and values during range-based for loops
- [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::begin](../basic_json_view/begin.md) - the same iteration on a zero-copy view (in document order,
- [`basic_json_view::begin`](../basic_json_view/begin.md) - the same iteration on a zero-copy view (in document order,
not sorted by key)
## Version history
+5 -4
View File
@@ -63,10 +63,11 @@ initialization of a binary array type, for backwards compatibility and so it doe
## See also
- [binary_t](binary_t.md) type for binary values
- [get_binary](get_binary.md) get a reference to the stored binary value
- [is_binary](is_binary.md) return whether the value is binary
- [byte_container_with_subtype](../byte_container_with_subtype/index.md) container for binary values with subtype
- [Binary formats](../../features/binary_formats/index.md) - formats that can store binary values
- [`binary_t`](binary_t.md) - type for binary values
- [`get_binary`](get_binary.md) - get a reference to the stored binary value
- [`is_binary`](is_binary.md) - return whether the value is binary
- [`byte_container_with_subtype`](../byte_container_with_subtype/index.md) - container for binary values with subtype
- [Binary Values](../../features/binary_values.md) - the article on binary values
## Version history
+7 -4
View File
@@ -41,7 +41,7 @@ represent a byte array in modern C++.
[`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
`reinterpret_cast`, which is only correct for byte-sized elements — a container like
`#!cpp std::vector<std::intptr_t>` will not work as `BinaryType`. The elements must be stored contiguously, and
the binary readers additionally require `resize()` and `operator[]`. See
[Template Parameter Requirements](../../features/types/template_parameters.md#binarytype) for the full list.
@@ -90,8 +90,9 @@ type `#!cpp binary_t*` must be dereferenced.
- MessagePack
- If a subtype is given and the binary array contains exactly 1, 2, 4, 8, or 16 elements, the fixext family (fixext1,
fixext2, fixext4, fixext8) is used. For other sizes, the ext family (ext8, ext16, ext32) is used. The subtype is
then added as a signed 8-bit integer.
fixext2, fixext4, fixext8, fixext16) is used. For other sizes, the ext family (ext8, ext16, ext32) is used. The
subtype is then written as the signed 8-bit ext type: subtypes 128 to 255 map to the negative (reserved) ext
types, and on reading the ext type is exposed as an unsigned subtype from 0 to 255.
- If no subtype is given, the bin family (bin8, bin16, bin32) is used.
- BSON
@@ -117,7 +118,9 @@ type `#!cpp binary_t*` must be dereferenced.
## See also
- [byte_container_with_subtype](../byte_container_with_subtype/index.md)
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [Binary formats](../../features/binary_formats/index.md) - formats that can store binary values
- [`byte_container_with_subtype`](../byte_container_with_subtype/index.md) - container type used by binary values
## Version history
@@ -0,0 +1,48 @@
# <small>nlohmann::basic_json::</small>bjdata_version_t
```cpp
enum class bjdata_version_t
{
draft2,
draft3
};
```
This enumeration is used in [`to_bjdata`](to_bjdata.md) to choose the version of the BJData specification to write:
draft2
: BJData Draft 2 (the default). Binary values are written as arrays of `U` integers, and ND-arrays with
`"_ArrayType_": "byte"` are written as regular objects, since the `B` marker is not part of Draft 2.
draft3
: BJData Draft 3. Binary values are written as `B` elements: as an optimized binary array (`[$B#`) if both `use_size`
and `use_type` are set, and as an array of `B`-prefixed elements otherwise. ND-arrays with
`"_ArrayType_": "byte"` are written as packed arrays (`[$B#[...]`).
Only the writer is affected by the version. [`from_bjdata`](from_bjdata.md) reads the markers of both drafts.
## Examples
??? example
The example below shows how the different values of the `bjdata_version_t` influence the serialization of a binary
value with [`to_bjdata`](to_bjdata.md).
```cpp
--8<-- "examples/bjdata_version_t.cpp"
```
Output:
```json
--8<-- "examples/bjdata_version_t.output"
```
## See also
- [to_bjdata](to_bjdata.md) serializes a JSON value to BJData
- [BJData](../../features/binary_formats/bjdata.md) - the article on the BJData format
## Version history
- Added in version 3.12.0.
+3 -1
View File
@@ -47,7 +47,9 @@ Boolean values are stored directly inside a `basic_json` type.
## See also
- [is_boolean](is_boolean.md) checks whether the JSON value is a boolean
- [`is_boolean`](is_boolean.md) - checks whether the JSON value is a boolean
- [Types](../../features/types/index.md) - how booleans are stored
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the `BooleanType` template parameter
## Version history
+10 -5
View File
@@ -6,7 +6,12 @@ const_iterator cbegin() const noexcept;
Returns an iterator to the first element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`cbegin()` points to the first element, like `begin()`, and `end()` to the position after
the last element; the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
@@ -38,11 +43,11 @@ Constant.
## See also
- [begin](begin.md) returns an iterator to the first element
- [cend](cend.md) returns a const iterator to one past the last element
- [crbegin](crbegin.md) returns a const reverse iterator to the last element
- [`begin`](begin.md) - returns an iterator to the first element
- [`cend`](cend.md) - returns a const iterator to one past the last element
- [`crbegin`](crbegin.md) - returns a const reverse iterator to the last element
- [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::cbegin](../basic_json_view/cbegin.md) - the same iteration on a zero-copy view
- [`basic_json_view::cbegin`](../basic_json_view/cbegin.md) - the same iteration on a zero-copy view
## Version history
@@ -15,11 +15,13 @@ error
: report a parse error in case of a tag (the `from_cbor` overloads throw a `parse_error` exception by default)
ignore
: ignore tags
: ignore tags (also in front of a text string map key)
store
: store tagged byte strings (for bytes 0xd8..0xdb) as binary values with the tag as subtype; other tagged values are
read as if the tag were ignored. If several tags precede a byte string, only the innermost one is stored.
read as if the tag were ignored. If several tags precede a byte string, only the tag directly in front of it is
stored, and only when it has the form 0xd8..0xdb (a tag 0..23 written as 0xc0..0xd7 is skipped). Tags in front of a
text string map key are skipped.
## Examples
@@ -40,8 +42,9 @@ store
## See also
- [from_cbor](from_cbor.md) deserializes a JSON value from CBOR
- [input_format_t](input_format_t.md) the enumeration of supported input formats
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [`from_cbor`](from_cbor.md) - deserializes a JSON value from CBOR
- [`input_format_t`](input_format_t.md) - the enumeration of supported input formats
- [CBOR](../../features/binary_formats/cbor.md) - the article on the CBOR format
## Version history
+10 -5
View File
@@ -6,7 +6,12 @@ const_iterator cend() const noexcept;
Returns an iterator to one past the last element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`cend()` points to the position after the last element, like `end()`, and `begin()` to
the first element; the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
@@ -38,11 +43,11 @@ Constant.
## See also
- [end](end.md) returns an iterator to one past the last element
- [cbegin](cbegin.md) returns a const iterator to the first element
- [crend](crend.md) returns a const reverse iterator to one before the first element
- [`end`](end.md) - returns an iterator to one past the last element
- [`cbegin`](cbegin.md) - returns a const iterator to the first element
- [`crend`](crend.md) - returns a const reverse iterator to one before the first element
- [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::cend](../basic_json_view/cend.md) - the same iteration on a zero-copy view
- [`basic_json_view::cend`](../basic_json_view/cend.md) - the same iteration on a zero-copy view
## Version history
+3 -2
View File
@@ -54,8 +54,9 @@ All iterators, pointers, and references related to this container are invalidate
## See also
- [erase](erase.md) removes elements from a JSON value
- [empty](empty.md) checks whether the JSON value has no elements
- [`erase`](erase.md) - removes elements from a JSON value
- [`empty`](empty.md) - checks whether the JSON value has no elements
- [Modifying values](../../features/modifying_values.md) - the article on modifying values
## Version history
+13 -5
View File
@@ -61,11 +61,18 @@ Strong exception safety: if an exception occurs, the original value stays intact
## Complexity
Logarithmic in the size of the JSON object.
1. Logarithmic in the size of the JSON object.
2. Logarithmic in the size of the JSON object.
3. At most one lookup per reference token of `ptr`, each logarithmic in the size of the container at that level:
O(*n* log *m*) for *n* reference tokens and containers of size at most *m*.
4. Deleted; a call with an integral argument does not compile.
## Notes
- This method always returns `#!cpp false` when executed on a JSON type that is not an object.
- Overloads (1) and (2) always return `#!cpp false` when executed on a JSON type that is not an object. Overload (3)
also works on arrays and on primitive values: the empty JSON pointer resolves in every JSON value (so
`#!cpp json(1).contains(""_json_pointer)` returns `#!cpp true`), and `#!cpp json({1, 2}).contains("/1"_json_pointer)`
returns `#!cpp true`.
- This method can be executed on any JSON value type.
- Calling this function with an integer argument (for example, `#!cpp contains(0)`) does not compile: such an argument
would otherwise implicitly convert to a null `#!cpp const char*` and, from there, cause undefined behavior when
@@ -134,9 +141,10 @@ Logarithmic in the size of the JSON object.
## See also
- [find](find.md) find a value in an object
- [count](count.md) returns the number of occurrences of a key
- [basic_json_view::contains](../basic_json_view/contains.md) - the same check on a zero-copy view
- [`find`](find.md) - find a value in an object
- [`count`](count.md) - returns the number of occurrences of a key
- [`basic_json_view::contains`](../basic_json_view/contains.md) - the same check on a zero-copy view
- [Element Access](../../features/element_access/index.md#does-this-key-exist) - how to test whether a key exists
## Version history
+4 -3
View File
@@ -85,9 +85,10 @@ Logarithmic in the size of the JSON object.
## See also
- [find](find.md) find a value in an object
- [contains](contains.md) checks whether a key exists
- [basic_json_view::count](../basic_json_view/count.md) - the same check on a zero-copy view
- [`find`](find.md) - find a value in an object
- [`contains`](contains.md) - checks whether a key exists
- [`basic_json_view::count`](../basic_json_view/count.md) - the same check on a zero-copy view
- [Element Access](../../features/element_access/index.md#does-this-key-exist) - how to test whether a key exists
## Version history
+10 -4
View File
@@ -6,7 +6,13 @@ const_reverse_iterator crbegin() const noexcept;
Returns an iterator to the reverse-beginning; that is, the last element.
![Illustration from cppreference.com](../../images/range-rbegin-rend.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-rbegin-rend.svg"
</div>
<p class="nj-caption" markdown>`crbegin()` points to the last element, like `rbegin()`, and `rend()` to the position
before the first element. The upper row is the reversed sequence and the lower row the forward sequence; dashed arrows
link each reverse iterator to the forward iterator it stores, and dashed cells are past-the-last positions.</p>
## Return value
@@ -38,9 +44,9 @@ Constant.
## See also
- [crend](crend.md) returns a const reverse iterator to one before the first element
- [rbegin](rbegin.md) returns a reverse iterator to the last element
- [cbegin](cbegin.md) returns a const iterator to the first element
- [`crend`](crend.md) - returns a const reverse iterator to one before the first element
- [`rbegin`](rbegin.md) - returns a reverse iterator to the last element
- [`cbegin`](cbegin.md) - returns a const iterator to the first element
- [Iterators](../../features/iterators.md) - the article on iterators
## Version history
+10 -4
View File
@@ -7,7 +7,13 @@ const_reverse_iterator crend() const noexcept;
Returns an iterator to the reverse-end; that is, one before the first element. This element acts as a placeholder,
attempting to access it results in undefined behavior.
![Illustration from cppreference.com](../../images/range-rbegin-rend.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-rbegin-rend.svg"
</div>
<p class="nj-caption" markdown>`crend()` points to the position before the first element, like `rend()`, and `rbegin()`
to the last element. The upper row is the reversed sequence and the lower row the forward sequence; dashed arrows link
each reverse iterator to the forward iterator it stores, and dashed cells are past-the-last positions.</p>
## Return value
@@ -39,9 +45,9 @@ Constant.
## See also
- [crbegin](crbegin.md) returns a const reverse iterator to the last element
- [rend](rend.md) returns a reverse iterator to one before the first element
- [cend](cend.md) returns a const iterator to one past the last element
- [`crbegin`](crbegin.md) - returns a const reverse iterator to the last element
- [`rend`](rend.md) - returns a reverse iterator to one before the first element
- [`cend`](cend.md) - returns a const iterator to one past the last element
- [Iterators](../../features/iterators.md) - the article on iterators
## Version history
@@ -32,8 +32,10 @@ The actual comparator used depends on [`object_t`](object_t.md) and can be obtai
## See also
- [object_comparator_t](object_comparator_t.md) the comparator actually used by `object_t`
- [object_t](object_t.md) the type used to store JSON objects
- [`object_comparator_t`](object_comparator_t.md) - the comparator actually used by `object_t`
- [`object_t`](object_t.md) - the type used to store JSON objects
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the `ObjectType` template parameter
- [Object order](../../features/object_order.md) - preserve the insertion order of keys
## Version history
+48 -9
View File
@@ -2,17 +2,28 @@
```cpp
static basic_json diff(const basic_json& source,
const basic_json& target);
const basic_json& target,
const string_t& path = "");
```
Creates a [JSON Patch](http://jsonpatch.com) so that value `source` can be changed into the value `target` by calling
[`patch`](patch.md) function.
For two JSON values `source` and `target`, the following code always yields `#!cpp true`:
For two JSON values `source` and `target`, the following code yields `#!cpp true`:
```cpp
source.patch(diff(source, target)) == target;
```
The equality holds up to [`operator==`](operator_eq.md), so it has the following exceptions:
- A value that is not equal to itself cannot round-trip. This applies to `NaN` (also nested in an array or object) and
to [discarded](is_discarded.md) values: `diff` emits a `replace` operation for them. A `NaN` in the patch is
serialized as `#!json null`, so a patch that was dumped and parsed again would set `#!json null`.
- Numbers that compare equal produce no operation, even if their types differ or if one is zero and the other is
negative zero: `diff(1, 1.0)` (integer and floating-point), `diff(1u, 1)` (unsigned and signed integer) and
`diff(0.0, -0.0)` (positive and negative zero) all return `#!json []`. The patched value is then the `source` and
keeps its number type and sign.
## Parameters
`source` (in)
@@ -21,6 +32,12 @@ source.patch(diff(source, target)) == target;
`target` (in)
: JSON value to compare against
`path` (in)
: a prefix that is put verbatim in front of the `path` member of every operation (default: `""`, which addresses the
root of the value). The prefix is neither escaped nor validated: `#!cpp diff(1, 2, "abc")` yields an operation with
the `path` `abc`, which is not a valid JSON Pointer. Use it with a valid JSON Pointer such as `/root` and escape
`~` and `/` in its reference tokens (see [JSON Pointer](../../features/json_pointer.md)).
## Return value
a JSON patch to convert the `source` to `target`
@@ -31,11 +48,32 @@ Strong guarantee: `source` and `target` are never modified.
## Complexity
Linear in the lengths of `source` and `target`.
Linear in the total number of values (including nested ones) in `source` and `target`, times the cost of a key-based
object operation (looking up a key in an object): logarithmic for [`json`](../json.md), and linear for
[`ordered_json`](../ordered_json.md) (see [`ordered_map` complexity](../ordered_map.md#complexity)). For
`ordered_json`, diffing two objects with `n` and `m` members therefore takes O((n+m)²) when their keys do not line up
(e.g., a key was added or the keys are in a different order). The size of the patch is proportional to the number of
operations times the length of their paths, so a small change deep inside a value yields a long `path`.
## Notes
Currently, only `remove`, `add`, and `replace` operations are generated.
- Currently, only `remove`, `add`, and `replace` operations are generated.
- The patch is correct, but not guaranteed to be minimal. For instance, `diff([1,2,3], [0,1,2,3])` yields three
`replace` operations and one `add` operation instead of a single insertion.
- Differences between two arrays are reported index by index. Elements that were added at the end of the array are added
with `add` operations on the path `/-` (appended in order), and elements that were removed are removed with `remove`
operations from the highest index down to the lowest, so that the remaining indices stay valid.
- For objects, the operations for the members of `source` come first (`replace`, `remove`, or the operations for nested
values, in the iteration order of `source`), followed by `add` operations for the members that only `target` has.
- For [`ordered_json`](../ordered_json.md), objects with the same keys in a different order are different. As a patch
cannot reorder members, `diff` removes all keys of the `source` object and adds them again in the order of the
`target`.
- If `source` and `target` differ as a whole (e.g., different types), the patch consists of a single `replace`
operation for the root of the value, i.e., with the `path` `""` (or the given `path` prefix).
- The `value` members of the patch hold copies of values of `target`. A [binary](../../features/binary_values.md) value
has no JSON representation: when a patch that contains one is serialized, it becomes an object such as
`#!json {"bytes":[1,3],"subtype":null}`, so a parsed patch no longer holds a binary value (and would set that object
instead).
## Examples
@@ -55,11 +93,12 @@ Currently, only `remove`, `add`, and `replace` operations are generated.
## See also
- [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
- [patch](patch.md) applies a JSON Patch
- [patch_inplace](patch_inplace.md) applies a JSON Patch in place
- [merge_patch](merge_patch.md) applies a JSON Merge Patch
- [merge_diff](merge_diff.md) creates a diff as a JSON Merge Patch
- [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - specification of JSON Patch
- [`patch`](patch.md) - applies a JSON Patch
- [`patch_inplace`](patch_inplace.md) - applies a JSON Patch in place
- [`merge_patch`](merge_patch.md) - applies a JSON Merge Patch
- [`merge_diff`](merge_diff.md) - creates a diff as a JSON Merge Patch
- [JSON Patch and Diff](../../features/json_patch.md) - the article on JSON Patch
## Version history
+3 -3
View File
@@ -89,9 +89,9 @@ Binary values are serialized as an object containing two keys:
## See also
- [to_string](to_string.md) returns a string representation of a JSON value
- [operator<<](../operator_ltlt.md) serialize to stream
- [`basic_json_view::dump`](../basic_json_view/dump.md) the corresponding function of `basic_json_view`, serializing
- [`to_string`](to_string.md) - returns a string representation of a JSON value
- [`operator<<`](../operator_ltlt.md) - serialize to stream
- [`basic_json_view::dump`](../basic_json_view/dump.md) - the corresponding function of `basic_json_view`, serializing
directly from a flat index without building a `basic_json` value
- [Serialization](../../features/serialization.md) - the serialization article
+2 -2
View File
@@ -63,8 +63,8 @@ Logarithmic in the size of the container, O(log(`size()`)).
## See also
- [emplace_back](emplace_back.md) add a value to an array
- [insert](insert.md) add values to an array/object
- [`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
@@ -61,8 +61,8 @@ Amortized constant.
## See also
- [operator+=](operator+=.md) add a value to an array/object
- [push_back](push_back.md) add a value to an array/object
- [`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
+4 -4
View File
@@ -41,7 +41,7 @@ bool empty() const noexcept
## Notes
This function does not return whether a string stored as JSON value is empty -- it returns whether the JSON container
This function does not return whether a string stored as JSON value is empty — it returns whether the JSON container
itself is empty which is `#!cpp false` in the case of a string.
## Examples
@@ -62,9 +62,9 @@ itself is empty which is `#!cpp false` in the case of a string.
## See also
- [size](size.md) returns the number of elements
- [clear](clear.md) clears the content and resets the value to the default value
- [basic_json_view::empty](../basic_json_view/empty.md) - the same check on a zero-copy view
- [`size`](size.md) - returns the number of elements
- [`clear`](clear.md) - clears the content and resets the value to the default value
- [`basic_json_view::empty`](../basic_json_view/empty.md) - the same check on a zero-copy view
## Version history
+10 -5
View File
@@ -7,7 +7,12 @@ const_iterator end() const noexcept;
Returns an iterator to one past the last element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`end()` points to the position after the last element and `begin()` to the first element;
the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
@@ -39,11 +44,11 @@ Constant.
## See also
- [begin](begin.md) returns an iterator to the first element
- [cend](cend.md) returns a const iterator to one past the last element
- [rend](rend.md) returns a reverse iterator to one before the first element
- [`begin`](begin.md) - returns an iterator to the first element
- [`cend`](cend.md) - returns a const iterator to one past the last element
- [`rend`](rend.md) - returns a reverse iterator to one before the first element
- [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::end](../basic_json_view/end.md) - the same iteration on a zero-copy view
- [`basic_json_view::end`](../basic_json_view/end.md) - the same iteration on a zero-copy view
## Version history
+3 -2
View File
@@ -60,8 +60,9 @@ Constant.
## See also
- [start_pos](start_pos.md) to access the start position
- [JSON_DIAGNOSTIC_POSITIONS](../macros/json_diagnostic_positions.md) for an overview of the diagnostic positions
- [`start_pos`](start_pos.md) - to access the start position
- [`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) - overview of the supported conversions
- [Parsing and Exceptions](../../features/parsing/parse_exceptions.md) - handling parse errors and locating them in the input
## Version history
+2 -2
View File
@@ -204,8 +204,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
## See also
- [clear](clear.md) clears the contents
- [insert](insert.md) add values to an array/object
- [`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
@@ -61,7 +61,7 @@ keep
## See also
- [dump](dump.md) serializes a JSON value, with an `error_handler_t` parameter to configure invalid UTF-8 handling
- [`dump`](dump.md) - serializes a JSON value, with an `error_handler_t` parameter to configure invalid UTF-8 handling
- [Handling invalid UTF-8](../../features/serialization.md#handling-invalid-utf-8) - the article on handling invalid UTF-8
## Version history
+8 -1
View File
@@ -40,6 +40,9 @@ classDiagram
style json_exception fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::exception`.</p>
Subclasses:
- [`parse_error`](parse_error.md) for exceptions indicating a parse error
@@ -80,7 +83,11 @@ constructor.
## See also
[List of exceptions](../../home/exceptions.md)
- [List of exceptions](../../home/exceptions.md) - overview of all exceptions thrown by the library
- [Working Without Exceptions](../../features/no_exceptions.md) - using the library without exceptions
- [`JSON_DIAGNOSTICS`](../macros/json_diagnostics.md) - extended exception messages with the path of the failing value
- [Parsing and Exceptions](../../features/parsing/parse_exceptions.md) - parsing alternatives that do not throw
- [Debugging](../../home/debugging.md) - debugging aids
## Version history
+4 -3
View File
@@ -91,10 +91,11 @@ Logarithmic in the size of the JSON object.
## See also
- [count](count.md) returns the number of occurrences of a key
- [contains](contains.md) checks whether a key exists
- [basic_json_view::find](../basic_json_view/find.md) - the same lookup on a zero-copy view (a duplicate key resolves
- [`count`](count.md) - returns the number of occurrences of a key
- [`contains`](contains.md) - checks whether a key exists
- [`basic_json_view::find`](../basic_json_view/find.md) - the same lookup on a zero-copy view (a duplicate key resolves
to the first member, whereas `parse()` keeps the last)
- [Element Access](../../features/element_access/index.md#does-this-key-exist) - how to test whether a key exists
## Version history
+2 -1
View File
@@ -58,7 +58,8 @@ Empty objects and arrays are flattened to `#!json null` and will not be reconstr
## See also
- [unflatten](unflatten.md) the reverse function
- [`unflatten`](unflatten.md) - the reverse function
- [JSON Pointer](../../features/json_pointer.md#flatten-unflatten) - the article on JSON Pointer and flattening
## Version history
+2 -2
View File
@@ -86,8 +86,8 @@ std::string format_as(const BasicJsonType& j)
## See also
- [dump](dump.md)
- [std::formatter<basic_json>](std_formatter.md) - the `std::format` (C++20) equivalent
- [`dump`](dump.md) - serialize a JSON value to a string
- [`std::formatter<basic_json>`](std_formatter.md) - the `std::format` (C++20) equivalent
- [Serialization](../../features/serialization.md) - the serialization article
## Version history
+14 -7
View File
@@ -82,8 +82,11 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string could not be parsed
successfully, or if a string value or object key is not valid UTF-8 and `error_handler` is `strict`
- Throws [parse_error.115](../../home/exceptions.md#jsonexceptionparse_error115) if the text of a high-precision
number (`H`) is not a valid number
- Throws [out_of_range.408](../../home/exceptions.md#jsonexceptionout_of_range408) if the size of an optimized container
or n-dimensional array cannot be represented by `std::size_t`
cannot be represented by `std::size_t` or exceeds the container's `max_size()`, or if the product of the dimensions of
an n-dimensional array overflows
## Complexity
@@ -107,12 +110,16 @@ Linear in the size of the input.
## See also
- [to_bjdata](to_bjdata.md) create a BJData serialization of a JSON value
- [from_cbor](from_cbor.md) create a JSON value from an input in CBOR format
- [from_msgpack](from_msgpack.md) create a JSON value from an input in MessagePack format
- [from_bson](from_bson.md) create a JSON value from an input in BSON format
- [from_ubjson](from_ubjson.md) create a JSON value from an input in UBJSON format
- [from_bon8](from_bon8.md) create a JSON value from an input in BON8 format
- [BJData](../../features/binary_formats/bjdata.md) - the format, its byte layout and how values are mapped
- [Binary formats](../../features/binary_formats/index.md) - overview and comparison of the supported binary formats
- [Parsing untrusted input](../../features/parsing/untrusted_input.md) - limits and safe handling of hostile data
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [`to_bjdata`](to_bjdata.md) - create a BJData serialization of a JSON value
- [`from_cbor`](from_cbor.md) - create a JSON value from an input in CBOR format
- [`from_msgpack`](from_msgpack.md) - create a JSON value from an input in MessagePack format
- [`from_bson`](from_bson.md) - create a JSON value from an input in BSON format
- [`from_ubjson`](from_ubjson.md) - create a JSON value from an input in UBJSON format
- [`from_bon8`](from_bon8.md) - create a JSON value from an input in BON8 format
## Version history
+14 -6
View File
@@ -74,6 +74,11 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs, for instance
an invalid byte, a string that is not valid UTF-8, or an object key that is not a string
The UTF-8 validity of strings is always checked, independent of
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md), because the end of a BON8 string is determined from
its encoding. Duplicate object keys are accepted; the last value wins (see
[BON8](../../features/binary_formats/bon8.md)).
## Complexity
Linear in the size of the input.
@@ -96,12 +101,15 @@ Linear in the size of the input.
## See also
- [to_bon8](to_bon8.md) create a BON8 serialization of a JSON value
- [from_cbor](from_cbor.md) create a JSON value from an input in CBOR format
- [from_msgpack](from_msgpack.md) create a JSON value from an input in MessagePack format
- [from_bson](from_bson.md) create a JSON value from an input in BSON format
- [from_ubjson](from_ubjson.md) create a JSON value from an input in UBJSON format
- [from_bjdata](from_bjdata.md) create a JSON value from an input in BJData format
- [BON8](../../features/binary_formats/bon8.md) - the format, its byte layout and how values are mapped
- [Binary formats](../../features/binary_formats/index.md) - overview and comparison of the supported binary formats
- [Parsing untrusted input](../../features/parsing/untrusted_input.md) - limits and safe handling of hostile data
- [`to_bon8`](to_bon8.md) - create a BON8 serialization of a JSON value
- [`from_cbor`](from_cbor.md) - create a JSON value from an input in CBOR format
- [`from_msgpack`](from_msgpack.md) - create a JSON value from an input in MessagePack format
- [`from_bson`](from_bson.md) - create a JSON value from an input in BSON format
- [`from_ubjson`](from_ubjson.md) - create a JSON value from an input in UBJSON format
- [`from_bjdata`](from_bjdata.md) - create a JSON value from an input in BJData format
## Version history
+13 -8
View File
@@ -80,7 +80,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
- Throws [`parse_error.110`](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely or
the end of the input was not reached when `strict` was set to true
- Throws [`parse_error.112`](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs (e.g., an
invalid string or byte array length)
invalid string or byte array length, an invalid inner length of a binary value with subtype `0x02`, or a document size
that does not match the content; `strict` does not affect the document size checks)
- Throws [`parse_error.114`](../../home/exceptions.md#jsonexceptionparse_error114) if an unsupported BSON record type is
encountered
- Throws [`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) if a string value or object key is
@@ -108,13 +109,17 @@ Linear in the size of the input.
## See also
- [BSON specification](http://bsonspec.org/spec.html)
- [to_bson](to_bson.md) for the analogous serialization
- [from_cbor](from_cbor.md) for the related CBOR format
- [from_msgpack](from_msgpack.md) for the related MessagePack format
- [from_ubjson](from_ubjson.md) for the related UBJSON format
- [from_bjdata](from_bjdata.md) for the related BJData format
- [from_bon8](from_bon8.md) for the related BON8 format
- [BSON](../../features/binary_formats/bson.md) - the format, its byte layout and how values are mapped
- [Binary formats](../../features/binary_formats/index.md) - overview and comparison of the supported binary formats
- [Parsing untrusted input](../../features/parsing/untrusted_input.md) - limits and safe handling of hostile data
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [BSON specification](http://bsonspec.org/spec.html) - specification of the BSON format
- [`to_bson`](to_bson.md) - the analogous serialization
- [`from_cbor`](from_cbor.md) - the related CBOR format
- [`from_msgpack`](from_msgpack.md) - the related MessagePack format
- [`from_ubjson`](from_ubjson.md) - the related UBJSON format
- [`from_bjdata`](from_bjdata.md) - the related BJData format
- [`from_bon8`](from_bon8.md) - the related BON8 format
## Version history
+22 -10
View File
@@ -32,8 +32,10 @@ The exact mapping and its limitations are described on a [dedicated page](../../
- an `std::istream` object
- a `FILE` pointer
- a C-style array of characters
- a pointer to a null-terminated string of single byte characters
- a C-style array of characters (its terminating NUL is read as trailing data: `parse_error.110` unless `strict` is
`false`)
- a pointer to a null-terminated string of single byte characters (read up to the first 0x00 byte, which is a valid
CBOR byte)
- 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`)
@@ -89,8 +91,14 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from CBOR were
used in the given input or if the input is not valid CBOR
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a map key is not a string (keys of
other types are not supported, as JSON object keys are always strings), or if a string value or object key is not
valid UTF-8 and `error_handler` is `strict`
other types are not supported, as JSON object keys are always strings), if the head of a string or byte string is
malformed (including a chunk of the wrong type or an indefinite-length string nested inside an indefinite-length
string), or if a string value or object key (or one chunk of an indefinite-length string) is not valid UTF-8 and
`error_handler` is `strict`
- Throws [out_of_range.408](../../home/exceptions.md#jsonexceptionout_of_range408) if an array or map announces
a length that `std::size_t` cannot hold, or that equals `std::size_t(-1)` (for example `9B FF FF FF FF FF FF FF FF`)
- Throws [out_of_range.406](../../home/exceptions.md#jsonexceptionout_of_range406) if a floating-point number does not
fit into `number_float_t`
## Complexity
@@ -114,12 +122,16 @@ Linear in the size of the input.
## See also
- [to_cbor](to_cbor.md) create a CBOR serialization of a JSON value
- [from_msgpack](from_msgpack.md) create a JSON value from an input in MessagePack format
- [from_bson](from_bson.md) create a JSON value from an input in BSON format
- [from_ubjson](from_ubjson.md) create a JSON value from an input in UBJSON format
- [from_bjdata](from_bjdata.md) create a JSON value from an input in BJData format
- [from_bon8](from_bon8.md) create a JSON value from an input in BON8 format
- [CBOR](../../features/binary_formats/cbor.md) - the format, its byte layout and how values are mapped
- [Binary formats](../../features/binary_formats/index.md) - overview and comparison of the supported binary formats
- [Parsing untrusted input](../../features/parsing/untrusted_input.md) - limits and safe handling of hostile data
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [`to_cbor`](to_cbor.md) - create a CBOR serialization of a JSON value
- [`from_msgpack`](from_msgpack.md) - create a JSON value from an input in MessagePack format
- [`from_bson`](from_bson.md) - create a JSON value from an input in BSON format
- [`from_ubjson`](from_ubjson.md) - create a JSON value from an input in UBJSON format
- [`from_bjdata`](from_bjdata.md) - create a JSON value from an input in BJData format
- [`from_bon8`](from_bon8.md) - create a JSON value from an input in BON8 format
## Version history
@@ -107,12 +107,16 @@ Linear in the size of the input.
## See also
- [to_msgpack](to_msgpack.md) create a MessagePack serialization of a JSON value
- [from_cbor](from_cbor.md) create a JSON value from an input in CBOR format
- [from_bson](from_bson.md) create a JSON value from an input in BSON format
- [from_ubjson](from_ubjson.md) create a JSON value from an input in UBJSON format
- [from_bjdata](from_bjdata.md) create a JSON value from an input in BJData format
- [from_bon8](from_bon8.md) create a JSON value from an input in BON8 format
- [MessagePack](../../features/binary_formats/messagepack.md) - the format, its byte layout and how values are mapped
- [Binary formats](../../features/binary_formats/index.md) - overview and comparison of the supported binary formats
- [Parsing untrusted input](../../features/parsing/untrusted_input.md) - limits and safe handling of hostile data
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [`to_msgpack`](to_msgpack.md) - create a MessagePack serialization of a JSON value
- [`from_cbor`](from_cbor.md) - create a JSON value from an input in CBOR format
- [`from_bson`](from_bson.md) - create a JSON value from an input in BSON format
- [`from_ubjson`](from_ubjson.md) - create a JSON value from an input in UBJSON format
- [`from_bjdata`](from_bjdata.md) - create a JSON value from an input in BJData format
- [`from_bon8`](from_bon8.md) - create a JSON value from an input in BON8 format
## Version history
+21 -10
View File
@@ -79,11 +79,18 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
- Throws [parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely or
the end of the file was not reached when `strict` was set to true
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if an invalid type marker is read
(including a type marker after `$` of an optimized container, even if its count is 0), or if `$` is not followed by `#`
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string could not be parsed
successfully, or if a string value or object key is not valid UTF-8 and `error_handler` is `strict`
- Throws [out_of_range.408](../../home/exceptions.md#jsonexceptionout_of_range408) if the size of an optimized container
or n-dimensional array cannot be represented by `std::size_t`
successfully (negative or non-integer length, `C` followed by a byte above 0x7F), if the count of an optimized
container is negative, or if a string value or object key is not valid UTF-8 and `error_handler` is `strict`
- Throws [parse_error.115](../../home/exceptions.md#jsonexceptionparse_error115) if the text of a high-precision number
(`H`) is not a valid JSON number
- Throws [out_of_range.406](../../home/exceptions.md#jsonexceptionout_of_range406) if a high-precision number, or a
float64 when `number_float_t` is `float`, does not fit into `number_float_t`
- Throws [out_of_range.408](../../home/exceptions.md#jsonexceptionout_of_range408) if the count of an optimized
container exceeds the capacity of the container (or of `std::size_t`), or if an optimized array of `Z`, `T`, or `F` has
more than 1,048,576 elements
## Complexity
@@ -107,12 +114,16 @@ Linear in the size of the input.
## See also
- [to_ubjson](to_ubjson.md) create a UBJSON serialization of a JSON value
- [from_cbor](from_cbor.md) create a JSON value from an input in CBOR format
- [from_msgpack](from_msgpack.md) create a JSON value from an input in MessagePack format
- [from_bson](from_bson.md) create a JSON value from an input in BSON format
- [from_bjdata](from_bjdata.md) create a JSON value from an input in BJData format
- [from_bon8](from_bon8.md) create a JSON value from an input in BON8 format
- [UBJSON](../../features/binary_formats/ubjson.md) - the format, its byte layout and how values are mapped
- [Binary formats](../../features/binary_formats/index.md) - overview and comparison of the supported binary formats
- [Parsing untrusted input](../../features/parsing/untrusted_input.md) - limits and safe handling of hostile data
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [`to_ubjson`](to_ubjson.md) - create a UBJSON serialization of a JSON value
- [`from_cbor`](from_cbor.md) - create a JSON value from an input in CBOR format
- [`from_msgpack`](from_msgpack.md) - create a JSON value from an input in MessagePack format
- [`from_bson`](from_bson.md) - create a JSON value from an input in BSON format
- [`from_bjdata`](from_bjdata.md) - create a JSON value from an input in BJData format
- [`from_bon8`](from_bon8.md) - create a JSON value from an input in BON8 format
## Version history
+3 -2
View File
@@ -50,9 +50,10 @@ Constant.
## See also
- [back](back.md) to access the last element
- [basic_json_view::front](../basic_json_view/front.md) - the same access on a zero-copy view (document order, not
- [`back`](back.md) - to access the last element
- [`basic_json_view::front`](../basic_json_view/front.md) - the same access on a zero-copy view (document order, not
sorted; duplicate keys are visited)
- [Element Access](../../features/element_access/index.md) - overview of all ways to access elements
## Version history
+6 -5
View File
@@ -178,13 +178,14 @@ overload (3).
## See also
- [get_to](get_to.md) convert and write into a passed value
- [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
- [`get_to`](get_to.md) - convert and write into a passed value
- [`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
- [basic_json_view::get](../basic_json_view/get.md) - the same conversion on a zero-copy view (many types are
- [`basic_json_view::get`](../basic_json_view/get.md) - the same conversion on a zero-copy view (many types are
converted without ever building a `basic_json` value)
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) - make your own types usable with `get`
## Version history
@@ -36,7 +36,7 @@ Constant.
## See also
- [basic_json](index.md#template-parameters) the class template, with `AllocatorType` as one of its template parameters
- [`basic_json`](index.md#template-parameters) - the class template, with `AllocatorType` as one of its template parameters
- [Template Parameter Requirements](../../features/types/template_parameters.md#allocatortype) - the requirements for `AllocatorType`
## Version history
@@ -42,8 +42,11 @@ Constant.
## See also
- [get](get.md) get a value (explicit conversion)
- [get_ref](get_ref.md) get a reference to the stored value
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [`binary`](binary.md) - create a binary value
- [`is_binary`](is_binary.md) - check whether a value is binary
- [`get`](get.md) - get a value (explicit conversion)
- [`get_ref`](get_ref.md) - get a reference to the stored value
## Version history
+2 -1
View File
@@ -86,7 +86,8 @@ Constant.
## See also
- [get_ref()](get_ref.md) get a reference value
- [`get_ref()`](get_ref.md) - get a reference value
- [Converting values](../../features/conversions.md) - getting values out, with or without copying
## Version history
+3 -2
View File
@@ -60,9 +60,10 @@ Constant.
## See also
- [get_ptr()](get_ptr.md) get a pointer value
- [basic_json_view::get_string](../basic_json_view/get_string.md) - the closest counterpart on a zero-copy view: a
- [`get_ptr()`](get_ptr.md) - get a pointer value
- [`basic_json_view::get_string`](../basic_json_view/get_string.md) - the closest counterpart on a zero-copy view: a
string without a copy, but as a view rather than a reference to a value that must already exist
- [Converting values](../../features/conversions.md) - getting values out, with or without copying
## Version history
+5 -4
View File
@@ -68,11 +68,12 @@ Depends on the `json_serializer<ValueType>::from_json()` implementation.
## See also
- [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
- [`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
- [basic_json_view::get_to](../basic_json_view/get_to.md) - the same conversion on a zero-copy view
- [`basic_json_view::get_to`](../basic_json_view/get_to.md) - the same conversion on a zero-copy view
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) - make your own types usable with `get_to`
## Version history
+10 -4
View File
@@ -121,6 +121,7 @@ The class satisfies the following concept requirements:
- [**json_pointer**](../json_pointer/index.md) - JSON Pointer implementation
- [**json_serializer**](json_serializer.md) - type of the serializer to for conversions from/to JSON
- [**error_handler_t**](error_handler_t.md) - type to choose behavior on decoding errors
- [**bjdata_version_t**](bjdata_version_t.md) - type to choose the BJData version to write
- [**cbor_tag_handler_t**](cbor_tag_handler_t.md) - type to choose how to handle CBOR tags
- **initializer_list_t** - type for initializer lists of `basic_json` values
- [**input_format_t**](input_format_t.md) - type to choose the format to parse
@@ -188,7 +189,7 @@ The class satisfies the following concept requirements:
Functions to inspect the type of a JSON value.
- [**type**](type.md) - return the type of the JSON value
- [**operator value_t**](operator_value_t.md) - return the type of the JSON value
- [`operator value_t`](operator_value_t.md) - return the type of the JSON value
- [**type_name**](type_name.md) - return the type as string
- [**is_primitive**](is_primitive.md) - return whether the type is primitive
- [**is_structured**](is_structured.md) - return whether the type is structured
@@ -217,7 +218,7 @@ Direct access to the stored value of a JSON value.
- [**get_to**](get_to.md) - get a value and write it to a destination
- [**get_ptr**](get_ptr.md) - get a pointer value
- [**get_ref**](get_ref.md) - get a reference value
- [**operator ValueType**](operator_ValueType.md) - get a value
- [`operator ValueType`](operator_ValueType.md) - get a value
- [**get_binary**](get_binary.md) - get a binary value
- [**as_base_class**](as_base_class.md) - access the custom base class
@@ -358,10 +359,15 @@ Access to the JSON value
## See also
- [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc8259)
- [basic_json_document](../basic_json_document/index.md) / [basic_json_view](../basic_json_view/index.md) - parse a JSON
- [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc8259) -
specification of the JSON data interchange format
- [`basic_json_document`](../basic_json_document/index.md) - / [`basic_json_view`](../basic_json_view/index.md) - parse a JSON
text into a flat index and read it through a view
- [Zero-copy JSON views](../../features/json_view.md) - when to use a document and a view instead of a `basic_json`
- [Types](../../features/types/index.md) - how JSON values are stored and which types exist
- [Converting values](../../features/conversions.md) - get values out of a JSON value and put values in
- [Creating JSON values](../../features/creating_values.md) - all the ways to build a JSON value
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) - convert your own types to and from JSON
## Version history
@@ -53,8 +53,9 @@ bon8
## See also
- [sax_parse](sax_parse.md) generic SAX parse interface, taking an `input_format_t` to select the input format
- [cbor_tag_handler_t](cbor_tag_handler_t.md) configures how CBOR tags are treated while parsing
- [`sax_parse`](sax_parse.md) - generic SAX parse interface, taking an `input_format_t` to select the input format
- [`cbor_tag_handler_t`](cbor_tag_handler_t.md) - configures how CBOR tags are treated while parsing
- [Binary Formats](../../features/binary_formats/index.md) - CBOR, MessagePack, BSON, and other formats
## Version history
+5 -4
View File
@@ -185,10 +185,11 @@ Strong exception safety: if an exception occurs, the original value stays intact
## See also
- [emplace](emplace.md) add a value to an object
- [emplace_back](emplace_back.md) add a value to an array
- [push_back](push_back.md) add a value to an array/object
- [update](update.md) merges objects
- [`emplace`](emplace.md) - add a value to an object
- [`emplace_back`](emplace_back.md) - add a value to an array
- [`push_back`](push_back.md) - add a value to an array/object
- [`update`](update.md) - merges objects
- [Modifying values](../../features/modifying_values.md) - the article on modifying values
## Version history
@@ -40,6 +40,9 @@ classDiagram
style json_invalid_iterator fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::invalid_iterator`.</p>
## Member functions
- **what** - returns explanatory string
@@ -66,12 +69,14 @@ classDiagram
## See also
- [`exception`](exception.md) for the base class of all exceptions thrown by the library
- [List of iterator errors](../../home/exceptions.md#iterator-errors)
- [`parse_error`](parse_error.md) for exceptions indicating a parse error
- [`type_error`](type_error.md) for exceptions indicating executing a member function with a wrong type
- [`out_of_range`](out_of_range.md) for exceptions indicating access out of the defined range
- [`other_error`](other_error.md) for exceptions indicating other library errors
- [`exception`](exception.md) - the base class of all exceptions thrown by the library
- [List of iterator errors](../../home/exceptions.md#iterator-errors) - overview of iterator errors (`invalid_iterator`)
- [`parse_error`](parse_error.md) - exceptions indicating a parse error
- [`type_error`](type_error.md) - exceptions indicating executing a member function with a wrong type
- [`out_of_range`](out_of_range.md) - exceptions indicating access out of the defined range
- [`other_error`](other_error.md) - exceptions indicating other library errors
- [Exceptions](../../home/exceptions.md) - all exceptions and their error codes
- [`JSON_DIAGNOSTICS`](../macros/json_diagnostics.md) - extended exception messages with the path of the failing value
## Version history
+6 -5
View File
@@ -36,11 +36,12 @@ Constant.
## See also
- [is_object](is_object.md) checks whether the JSON value is an object
- [is_structured](is_structured.md) checks whether the JSON value is structured (array or object)
- [type](type.md) returns the type of the JSON value
- [array_t](array_t.md) the type used to store JSON arrays
- [basic_json_view::is_array](../basic_json_view/is_array.md) - the same check on a zero-copy view
- [`is_object`](is_object.md) - checks whether the JSON value is an object
- [`is_structured`](is_structured.md) - checks whether the JSON value is structured (array or object)
- [`type`](type.md) - returns the type of the JSON value
- [`array_t`](array_t.md) - the type used to store JSON arrays
- [`basic_json_view::is_array`](../basic_json_view/is_array.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
+5 -4
View File
@@ -36,10 +36,11 @@ Constant.
## See also
- [is_primitive](is_primitive.md) checks whether the JSON value is primitive
- [binary_t](binary_t.md) the type used to store binary values
- [get_binary](get_binary.md) returns a reference to the stored binary value
- [basic_json_view::is_binary](../basic_json_view/is_binary.md) - the same check on a zero-copy view
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [`is_primitive`](is_primitive.md) - checks whether the JSON value is primitive
- [`binary_t`](binary_t.md) - the type used to store binary values
- [`get_binary`](get_binary.md) - returns a reference to the stored binary value
- [`basic_json_view::is_binary`](../basic_json_view/is_binary.md) - the same check on a zero-copy view
## Version history
@@ -36,9 +36,10 @@ Constant.
## See also
- [boolean_t](boolean_t.md) the type used to store JSON booleans
- [is_primitive](is_primitive.md) checks whether the JSON value is primitive
- [basic_json_view::is_boolean](../basic_json_view/is_boolean.md) - the same check on a zero-copy view
- [`boolean_t`](boolean_t.md) - the type used to store JSON booleans
- [`is_primitive`](is_primitive.md) - checks whether the JSON value is primitive
- [`basic_json_view::is_boolean`](../basic_json_view/is_boolean.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
@@ -87,8 +87,9 @@ with `allow_exceptions` set to `#!cpp false`: a parse error then yields a discar
## See also
- [basic_json_view::is_discarded](../basic_json_view/is_discarded.md) - the corresponding check on a zero-copy view,
- [`basic_json_view::is_discarded`](../basic_json_view/is_discarded.md) - the corresponding check on a zero-copy view,
which is `#!cpp true` if the view refers to no value
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
+6 -5
View File
@@ -36,11 +36,12 @@ Constant.
## See also
- [is_array](is_array.md) checks whether the JSON value is an array
- [is_object](is_object.md) checks whether the JSON value is an object
- [type](type.md) returns the type of the JSON value
- [value_t](value_t.md) the enumeration of JSON types
- [basic_json_view::is_null](../basic_json_view/is_null.md) - the same check on a zero-copy view
- [`is_array`](is_array.md) - checks whether the JSON value is an array
- [`is_object`](is_object.md) - checks whether the JSON value is an object
- [`type`](type.md) - returns the type of the JSON value
- [`value_t`](value_t.md) - the enumeration of JSON types
- [`basic_json_view::is_null`](../basic_json_view/is_null.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
+6 -4
View File
@@ -46,10 +46,12 @@ constexpr bool is_number() const noexcept
## See also
- [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number
- [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number
- [is_number_float()](is_number_float.md) check if the value is a floating-point number
- [basic_json_view::is_number](../basic_json_view/is_number.md) - the same check on a zero-copy view
- [`is_number_integer()`](is_number_integer.md) - check if the value is an integer or unsigned integer number
- [`is_number_unsigned()`](is_number_unsigned.md) - check if the value is an unsigned integer number
- [`is_number_float()`](is_number_float.md) - check if the value is a floating-point number
- [`basic_json_view::is_number`](../basic_json_view/is_number.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
- [Number Handling](../../features/types/number_handling.md) - how numbers are stored and converted
## Version history
@@ -37,10 +37,12 @@ Constant.
## See also
- [is_number()](is_number.md) check if the value is a number
- [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number
- [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number
- [basic_json_view::is_number_float](../basic_json_view/is_number_float.md) - the same check on a zero-copy view
- [`is_number()`](is_number.md) - check if the value is a number
- [`is_number_integer()`](is_number_integer.md) - check if the value is an integer or unsigned integer number
- [`is_number_unsigned()`](is_number_unsigned.md) - check if the value is an unsigned integer number
- [`basic_json_view::is_number_float`](../basic_json_view/is_number_float.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
- [Number Handling](../../features/types/number_handling.md) - how numbers are stored and converted
## Version history
@@ -37,10 +37,12 @@ Constant.
## See also
- [is_number()](is_number.md) check if the value is a number
- [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number
- [is_number_float()](is_number_float.md) check if the value is a floating-point number
- [basic_json_view::is_number_integer](../basic_json_view/is_number_integer.md) - the same check on a zero-copy view
- [`is_number()`](is_number.md) - check if the value is a number
- [`is_number_unsigned()`](is_number_unsigned.md) - check if the value is an unsigned integer number
- [`is_number_float()`](is_number_float.md) - check if the value is a floating-point number
- [`basic_json_view::is_number_integer`](../basic_json_view/is_number_integer.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
- [Number Handling](../../features/types/number_handling.md) - how numbers are stored and converted
## Version history
@@ -40,10 +40,12 @@ Constant.
## See also
- [is_number()](is_number.md) check if the value is a number
- [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number
- [is_number_float()](is_number_float.md) check if the value is a floating-point number
- [basic_json_view::is_number_unsigned](../basic_json_view/is_number_unsigned.md) - the same check on a zero-copy view
- [`is_number()`](is_number.md) - check if the value is a number
- [`is_number_integer()`](is_number_integer.md) - check if the value is an integer or unsigned integer number
- [`is_number_float()`](is_number_float.md) - check if the value is a floating-point number
- [`basic_json_view::is_number_unsigned`](../basic_json_view/is_number_unsigned.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
- [Number Handling](../../features/types/number_handling.md) - how numbers are stored and converted
## Version history
+6 -5
View File
@@ -36,11 +36,12 @@ Constant.
## See also
- [is_array](is_array.md) checks whether the JSON value is an array
- [is_structured](is_structured.md) checks whether the JSON value is structured (array or object)
- [type](type.md) returns the type of the JSON value
- [object_t](object_t.md) the type used to store JSON objects
- [basic_json_view::is_object](../basic_json_view/is_object.md) - the same check on a zero-copy view
- [`is_array`](is_array.md) - checks whether the JSON value is an array
- [`is_structured`](is_structured.md) - checks whether the JSON value is structured (array or object)
- [`type`](type.md) - returns the type of the JSON value
- [`object_t`](object_t.md) - the type used to store JSON objects
- [`basic_json_view::is_object`](../basic_json_view/is_object.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
@@ -56,13 +56,14 @@ This library extends primitive types to binary types, because binary types are r
## See also
- [is_structured()](is_structured.md) returns whether the JSON value is structured
- [is_null()](is_null.md) returns whether the JSON value is `null`
- [is_string()](is_string.md) returns whether the JSON value is a string
- [is_boolean()](is_boolean.md) returns whether the JSON value is a boolean
- [is_number()](is_number.md) returns whether the JSON value is a number
- [is_binary()](is_binary.md) returns whether the JSON value is a binary array
- [basic_json_view::is_primitive](../basic_json_view/is_primitive.md) - the same check on a zero-copy view
- [`is_structured()`](is_structured.md) - returns whether the JSON value is structured
- [`is_null()`](is_null.md) - returns whether the JSON value is `null`
- [`is_string()`](is_string.md) - returns whether the JSON value is a string
- [`is_boolean()`](is_boolean.md) - returns whether the JSON value is a boolean
- [`is_number()`](is_number.md) - returns whether the JSON value is a number
- [`is_binary()`](is_binary.md) - returns whether the JSON value is a binary array
- [`basic_json_view::is_primitive`](../basic_json_view/is_primitive.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
+5 -4
View File
@@ -36,10 +36,11 @@ Constant.
## See also
- [is_primitive](is_primitive.md) checks whether the JSON value is primitive
- [type](type.md) returns the type of the JSON value
- [string_t](string_t.md) the type used to store JSON strings
- [basic_json_view::is_string](../basic_json_view/is_string.md) - the same check on a zero-copy view
- [`is_primitive`](is_primitive.md) - checks whether the JSON value is primitive
- [`type`](type.md) - returns the type of the JSON value
- [`string_t`](string_t.md) - the type used to store JSON strings
- [`basic_json_view::is_string`](../basic_json_view/is_string.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
@@ -54,10 +54,11 @@ Note that though strings are containers in C++, they are treated as primitive va
## See also
- [is_primitive()](is_primitive.md) returns whether JSON value is primitive
- [is_array()](is_array.md) returns whether the value is an array
- [is_object()](is_object.md) returns whether the value is an object
- [basic_json_view::is_structured](../basic_json_view/is_structured.md) - the same check on a zero-copy view
- [`is_primitive()`](is_primitive.md) - returns whether JSON value is primitive
- [`is_array()`](is_array.md) - returns whether the value is an array
- [`is_object()`](is_object.md) - returns whether the value is an object
- [`basic_json_view::is_structured`](../basic_json_view/is_structured.md) - the same check on a zero-copy view
- [Types](../../features/types/index.md) - the JSON value types and how they are stored
## Version history
+5 -4
View File
@@ -54,7 +54,7 @@ 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
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
@@ -97,10 +97,11 @@ When iterating over an array, `key()` will return the index of the element as st
## See also
- [begin](begin.md) returns an iterator to the first element
- [end](end.md) returns an iterator to one past the last element
- [basic_json_view::items](../basic_json_view/items.md) - the same range on a zero-copy view (`#!cpp const auto`,
- [`begin`](begin.md) - returns an iterator to the first element
- [`end`](end.md) - returns an iterator to one past the last element
- [`basic_json_view::items`](../basic_json_view/items.md) - the same range on a zero-copy view (`#!cpp const auto`,
not `#!cpp const auto&`: items are produced on the fly; document order, not sorted; duplicate keys are visited)
- [Iterators](../../features/iterators.md#access-object-keys-during-iteration) - the article on iterating over keys and values
## Version history
@@ -57,7 +57,7 @@ same name. Hidden members remain accessible via [`as_base_class`](as_base_class.
## See also
- [as_base_class](as_base_class.md) - access the custom base class
- [`as_base_class`](as_base_class.md) - access the custom base class
- [Template Parameter Requirements](../../features/types/template_parameters.md#custombaseclass) - the requirements for `CustomBaseClass`
## Version history
@@ -44,10 +44,11 @@ deserializes. See [Template Parameter Requirements](../../features/types/templat
## See also
- [adl_serializer](../adl_serializer/index.md) the default `json_serializer`
- [get](get.md) explicit type conversion using the `json_serializer`'s `from_json()` method
- [get_to](get_to.md) explicit type conversion into a variable using the `json_serializer`'s `from_json()` method
- [`adl_serializer`](../adl_serializer/index.md) - the default `json_serializer`
- [`get`](get.md) - explicit type conversion using the `json_serializer`'s `from_json()` method
- [`get_to`](get_to.md) - explicit type conversion into a variable using the `json_serializer`'s `from_json()` method
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) - the article on converting between JSON values and arbitrary types
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the `JSONSerializer` template parameter
## Version history
+4 -4
View File
@@ -33,7 +33,7 @@ constant complexity.
## Notes
This function does not return the maximal length of a string stored as JSON value -- it returns the maximal number of
This function does not return the maximal length of a string stored as JSON value — it returns the maximal number of
string elements the JSON value can store which is `1`.
## Examples
@@ -56,9 +56,9 @@ string elements the JSON value can store which is `1`.
## See also
- [size](size.md) returns the number of elements
- [array_t](array_t.md) the type used to store JSON arrays
- [object_t](object_t.md) the type used to store JSON objects
- [`size`](size.md) - returns the number of elements
- [`array_t`](array_t.md) - the type used to store JSON arrays
- [`object_t`](object_t.md) - the type used to store JSON objects
## Version history
@@ -70,9 +70,10 @@ object operation (looking up a key, or adding one to the patch): logarithmic for
## See also
- [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
- [merge_patch](merge_patch.md) applies a JSON Merge Patch
- [diff](diff.md) creates a diff as a JSON Patch
- [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) - specification of JSON Merge Patch
- [`merge_patch`](merge_patch.md) - applies a JSON Merge Patch
- [`diff`](diff.md) - creates a diff as a JSON Patch
- [JSON Merge Patch](../../features/merge_patch.md) - the article on JSON Merge Patch
## Version history
+28 -7
View File
@@ -39,13 +39,33 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
## Complexity
Linear in the lengths of `apply_patch`.
Linear in the total number of values (including nested ones) in `apply_patch`, times the cost of a key-based object
operation (looking up, adding, or erasing a member): logarithmic for [`json`](../json.md), and linear for
[`ordered_json`](../ordered_json.md) (see [`ordered_map` complexity](../ordered_map.md#complexity)). For
`ordered_json`, patching an object that has `n` members with a patch that has `m` members therefore takes O(n·m). The
cost also includes one copy of `apply_patch` (see the notes below).
## Notes
`apply_patch` may be `#!cpp *this` itself or refer to a value contained in `#!cpp *this` (for example, a subobject
returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was called, before any modification of
`#!cpp *this`.
- `apply_patch` may be `#!cpp *this` itself or refer to a value contained in `#!cpp *this` (for example, a subobject
returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was called, before any modification of
`#!cpp *this`. To make this possible, the function copies `apply_patch` before it modifies `#!cpp *this`, so the cost
includes one copy of the patch.
- A merge patch uses `#!json null` to remove a member, so it cannot set a member to `#!json null`: applying
`#!json {"a":null}` to `#!json {"a":1}` gives `#!json {}`.
- Arrays are not merged: an array in the patch replaces the target value as a whole, and a `#!json null` inside an
array is kept as an element. `#!json null` members of the target that the patch does not mention are preserved.
- A `#!json null` in the patch only removes a member; it does not prevent the creation of the enclosing objects.
Applying `#!json {"a":{"b":null}}` to `#!json {}` gives `#!json {"a":{}}` (see example 15 in Appendix A of the RFC).
- If `apply_patch` is not an object, it replaces the target as a whole. In particular, a `#!json null` patch turns the
target into `#!json null`. If `apply_patch` is an object and the target is not, the target is first replaced by an
empty object, so applying `#!json {}` to `#!json 1` gives `#!json {}`.
- A merge patch cannot express every change; for example, it cannot reorder array elements or remove a specific array
element. Use [JSON Patch](../../features/json_patch.md) ([RFC 6902](https://tools.ietf.org/html/rfc6902)) for that.
[`merge_diff`](merge_diff.md) has a matching limitation, see its notes.
- A [discarded](is_discarded.md) value is treated like any other non-object value: a discarded
`apply_patch` turns the target into a discarded value, and an object patch replaces a discarded target by an object
as described above.
## Examples
@@ -65,9 +85,10 @@ returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was
## See also
- [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
- [patch](patch.md) apply a JSON patch
- [merge_diff](merge_diff.md) creates a diff as a JSON Merge Patch
- [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) - specification of JSON Merge Patch
- [`patch`](patch.md) - apply a JSON patch
- [`merge_diff`](merge_diff.md) - creates a diff as a JSON Merge Patch
- [JSON Merge Patch](../../features/merge_patch.md) - the article on JSON Merge Patch
## Version history
+5 -2
View File
@@ -48,8 +48,11 @@ Constant.
## See also
- [**NLOHMANN_JSON_VERSION_MAJOR**/**NLOHMANN_JSON_VERSION_MINOR**/**NLOHMANN_JSON_VERSION_PATCH**](../macros/nlohmann_json_version_major.md)
\- library version information
- [`NLOHMANN_JSON_VERSION_MAJOR`](../macros/nlohmann_json_version_major.md) /
[`NLOHMANN_JSON_VERSION_MINOR`](../macros/nlohmann_json_version_major.md) /
[`NLOHMANN_JSON_VERSION_PATCH`](../macros/nlohmann_json_version_major.md) - library version information
- [Integration](../../integration/index.md) - integrate the library
- [Supported Macros](../../features/macros.md) - guide to all supported macros
## Version history
@@ -84,10 +84,11 @@ Floating-point number values are stored directly inside a `basic_json` type.
## See also
- [number_integer_t](number_integer_t.md) the type used to store JSON integer numbers
- [number_unsigned_t](number_unsigned_t.md) the type used to store JSON unsigned integer numbers
- [is_number_float](is_number_float.md) checks whether the JSON value is a floating-point number
- [`number_integer_t`](number_integer_t.md) - the type used to store JSON integer numbers
- [`number_unsigned_t`](number_unsigned_t.md) - the type used to store JSON unsigned integer numbers
- [`is_number_float`](is_number_float.md) - checks whether the JSON value is a floating-point number
- [Number Handling](../../features/types/number_handling.md) - the article on number handling
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the number template parameters
## Version history
@@ -80,10 +80,11 @@ Integer number values are stored directly inside a `basic_json` type.
## See also
- [number_unsigned_t](number_unsigned_t.md) the type used to store JSON unsigned integer numbers
- [number_float_t](number_float_t.md) the type used to store JSON floating-point numbers
- [is_number_integer](is_number_integer.md) checks whether the JSON value is a signed integer number
- [`number_unsigned_t`](number_unsigned_t.md) - the type used to store JSON unsigned integer numbers
- [`number_float_t`](number_float_t.md) - the type used to store JSON floating-point numbers
- [`is_number_integer`](is_number_integer.md) - checks whether the JSON value is a signed integer number
- [Number Handling](../../features/types/number_handling.md) - the article on number handling
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the number template parameters
## Version history
@@ -82,10 +82,11 @@ Integer number values are stored directly inside a `basic_json` type.
## See also
- [number_integer_t](number_integer_t.md) the type used to store JSON integer numbers
- [number_float_t](number_float_t.md) the type used to store JSON floating-point numbers
- [is_number_unsigned](is_number_unsigned.md) checks whether the JSON value is an unsigned integer number
- [`number_integer_t`](number_integer_t.md) - the type used to store JSON integer numbers
- [`number_float_t`](number_float_t.md) - the type used to store JSON floating-point numbers
- [`is_number_unsigned`](is_number_unsigned.md) - checks whether the JSON value is an unsigned integer number
- [Number Handling](../../features/types/number_handling.md) - the article on number handling
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the number template parameters
## Version history
@@ -27,8 +27,10 @@ and [`default_object_comparator_t`](default_object_comparator_t.md) otherwise.
## See also
- [object_t](object_t.md) the type used to store JSON objects
- [default_object_comparator_t](default_object_comparator_t.md) the fallback comparator used when `object_t` has no `key_compare` member type
- [`object_t`](object_t.md) - the type used to store JSON objects
- [`default_object_comparator_t`](default_object_comparator_t.md) - the fallback comparator used when `object_t` has no `key_compare` member type
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the `ObjectType` template parameter
- [Object order](../../features/object_order.md) - preserve the insertion order of keys
## Version history
+6 -4
View File
@@ -20,7 +20,7 @@ To store objects in C++, a type is defined by the template parameters described
`ObjectType`
: the container to store objects. Its template parameters must have the same order and meaning as those of
`std::map`; in particular, the third parameter is a comparator. `#!cpp std::unordered_map`, whose third parameter
is a hash function, therefore needs an adapter -- see
is a hash function, therefore needs an adapter — see
[Template Parameter Requirements](../../features/types/template_parameters.md#objecttype) for the full list of
requirements, an adapter example, and the containers that are known to work.
@@ -125,10 +125,12 @@ the object is silently converted as an array of key-value pairs, which is incorr
## See also
- [array_t](array_t.md) the type used to store JSON arrays
- [string_t](string_t.md) the type used to store JSON strings
- [object_comparator_t](object_comparator_t.md) the comparator used to order object keys
- [`array_t`](array_t.md) - the type used to store JSON arrays
- [`string_t`](string_t.md) - the type used to store JSON strings
- [`object_comparator_t`](object_comparator_t.md) - the comparator used to order object keys
- [Object Order](../../features/object_order.md) - the article on object key ordering
- [Types](../../features/types/index.md) - how objects are stored
- [Template Parameter Requirements](../../features/types/template_parameters.md) - requirements on the `ObjectType` template parameter
## Version history
@@ -123,8 +123,9 @@ interpreted as `object_t::value_type` or `std::initializer_list<basic_json>`, se
## See also
- [emplace_back](emplace_back.md) add a value to an array
- [push_back](push_back.md) add a value to an array/object
- [`emplace_back`](emplace_back.md) - add a value to an array
- [`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
+3 -2
View File
@@ -45,8 +45,9 @@ Linear.
## See also
- [basic_json](basic_json.md) create a JSON value
- [swap](swap.md) exchanges the contents of two JSON values
- [`basic_json`](basic_json.md) - create a JSON value
- [`swap`](swap.md) - exchanges the contents of two JSON values
- [Creating JSON values](../../features/creating_values.md) - ways to create and assign JSON values
## Version history
+34 -11
View File
@@ -92,12 +92,20 @@ Strong exception safety: if an exception occurs, the original value stays intact
For the **const** version, an object key or array index in `ptr` that does not exist is not reported by an
exception, but is undefined behavior (see the notes below). Use [`at`](at.md) for checked access.
If the **non-const** version throws, the value is left unchanged: values it created for earlier reference tokens
of `ptr` are removed again. This also holds for exceptions such as `#!cpp std::bad_alloc` or
`#!cpp std::length_error` thrown while padding an array up to a very large index. With custom
[template parameters](../../features/types/template_parameters.md), this requires that `erase()` of the object and
array types and the move operations of the custom base class do not throw.
## Complexity
1. Constant if `idx` is in the range of the array. Otherwise, linear in `idx - size()`.
2. Logarithmic in the size of the container.
3. Logarithmic in the size of the container.
4. Logarithmic in the size of the container.
4. Linear in the number of reference tokens of `ptr`; for each of them, logarithmic in the size of the object, or
constant for an array. When the non-const version pads an array with `#!json null` values, it is additionally
linear in `idx - size()` for that array.
## Notes
@@ -137,10 +145,21 @@ Strong exception safety: if an exception occurs, the original value stays intact
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).
pointer token is a valid array index: the token `0`, a sequence of digits that does not begin with `0`,
or the token `-` creates an array, and every other 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. Tokens such as `01` or the empty token cannot be array indices (cf. RFC 6901, Sect. 4)
and therefore create objects, just as they would if the level already existed as an object. 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).
!!! warning "Large array indices"
As the array is filled up with `#!json null` values to the given index, the memory used grows with the index
and not with the size of the pointer: on a 64-bit platform, the index `10000000` allocates about 160 MB.
The library does not limit the index, so check the array indices of a JSON pointer from untrusted input
before using it with the non-const version. See
[Parsing untrusted input](../../features/parsing/untrusted_input.md#json-pointers-and-flattened-keys).
!!! warning "Deprecation"
@@ -271,13 +290,15 @@ Strong exception safety: if an exception occurs, the original value stays intact
## See also
- documentation on [unchecked access](../../features/element_access/unchecked_access.md)
- documentation on [runtime assertions](../../features/assertions.md)
- see [`at`](at.md) for access by reference with range checking
- see [`value`](value.md) for access with default value
- [basic_json_view::operator[]](../basic_json_view/operator%5B%5D.md) - the same access on a zero-copy view (a duplicate
- [Unchecked access](../../features/element_access/unchecked_access.md) - element access without range checking
- [Runtime assertions](../../features/assertions.md) - assertions guarding against undefined behavior
- [`at`](at.md) - access by reference with range checking
- [`value`](value.md) - access with default value
- [`basic_json_view::operator[]`](../basic_json_view/operator%5B%5D.md) - the same access on a zero-copy view (a duplicate
key resolves to the first member, whereas `parse()` keeps the last; a missing key gives a discarded view instead of
undefined behavior)
- [Element Access](../../features/element_access/index.md) - overview of all ways to access elements
- [JSON Pointer](../../features/json_pointer.md) - access nested values with a pointer
## Version history
@@ -291,4 +312,6 @@ Strong exception safety: if an exception occurs, the original value stays intact
4. Added in version 2.0.0. A missing array index in the const version is guarded by a runtime assertion since
version 3.13.0. Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) for a one-character array index that is not
a digit (e.g., `/x`) in version 3.13.0, as it already did for longer ones.
a digit (e.g., `/x`) in version 3.13.0, as it already did for longer ones. Fixed in version 3.13.0 to leave the value
unchanged if the non-const version throws (strong exception safety, as documented); before, values created for earlier
reference tokens of `ptr` were kept.
@@ -84,7 +84,7 @@ Linear in the size of the JSON value.
## See also
- [get](get.md) get a value (explicit conversion)
- [`get`](get.md) - get a value (explicit conversion)
- [Converting values](../../features/conversions.md) - the type conversions article
## Version history
@@ -168,9 +168,9 @@ Linear.
## See also
- [operator!=](operator_ne.md) compare for inequality
- [operator<=>](operator_spaceship.md) comparison: 3-way (C++20)
- [basic_json_view::operator==](../basic_json_view/operator_eq.md) - the same comparison on a zero-copy view, without
- [`operator!=`](operator_ne.md) - compare for inequality
- [`operator<=>`](operator_spaceship.md) - comparison: 3-way (C++20)
- [`basic_json_view::operator==`](../basic_json_view/operator_eq.md) - the same comparison on a zero-copy view, without
building a `basic_json` value for it
## Version history
@@ -93,7 +93,7 @@ Linear.
## See also
- [**operator<=>**](operator_spaceship.md) comparison: 3-way
- [`operator<=>`](operator_spaceship.md) - comparison: 3-way
## Version history
@@ -83,7 +83,7 @@ Linear.
## See also
- [**operator<=>**](operator_spaceship.md) comparison: 3-way
- [`operator<=>`](operator_spaceship.md) - comparison: 3-way
## Version history
@@ -94,7 +94,7 @@ Linear.
## See also
- [**operator<=>**](operator_spaceship.md) comparison: 3-way
- [`operator<=>`](operator_spaceship.md) - comparison: 3-way
## Version history
@@ -94,7 +94,7 @@ Linear.
## See also
- [**operator<=>**](operator_spaceship.md) comparison: 3-way
- [`operator<=>`](operator_spaceship.md) - comparison: 3-way
## Version history
@@ -93,9 +93,9 @@ Linear.
## See also
- [operator==](operator_eq.md) comparison: equal
- [operator<=>](operator_spaceship.md) comparison: 3-way (C++20)
- [basic_json_view::operator!=](../basic_json_view/operator_ne.md) - the same comparison on a zero-copy view, without
- [`operator==`](operator_eq.md) - comparison: equal
- [`operator<=>`](operator_spaceship.md) - comparison: 3-way (C++20)
- [`basic_json_view::operator!=`](../basic_json_view/operator_ne.md) - the same comparison on a zero-copy view, without
building a `basic_json` value for it
## Version history
Loaded 100 of 518 files, more files were not shown because too many files have changed in this diff. Show more