From 7f591adb5538e75393b077b96252425edcb1fb06 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 26 Oct 2026 21:15:53 +0100 Subject: [PATCH] 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 --- .../docs/api/adl_serializer/from_json.md | 2 +- docs/mkdocs/docs/api/basic_json/array.md | 4 +- docs/mkdocs/docs/api/basic_json/basic_json.md | 2 +- docs/mkdocs/docs/api/basic_json/binary_t.md | 2 +- .../docs/api/basic_json/cbor_tag_handler_t.md | 2 +- docs/mkdocs/docs/api/basic_json/empty.md | 2 +- docs/mkdocs/docs/api/basic_json/from_bon8.md | 2 +- docs/mkdocs/docs/api/basic_json/from_bson.md | 2 +- docs/mkdocs/docs/api/basic_json/from_cbor.md | 2 +- .../mkdocs/docs/api/basic_json/from_ubjson.md | 2 +- docs/mkdocs/docs/api/basic_json/items.md | 2 +- docs/mkdocs/docs/api/basic_json/max_size.md | 2 +- docs/mkdocs/docs/api/basic_json/object_t.md | 2 +- docs/mkdocs/docs/api/basic_json/size.md | 2 +- docs/mkdocs/docs/api/basic_json/string_t.md | 2 +- docs/mkdocs/docs/api/basic_json/to_bon8.md | 2 +- docs/mkdocs/docs/api/basic_json/to_bson.md | 2 +- docs/mkdocs/docs/api/basic_json/to_cbor.md | 2 +- docs/mkdocs/docs/api/basic_json/to_ubjson.md | 2 +- docs/mkdocs/docs/api/basic_json/type_name.md | 2 +- .../docs/api/basic_json_document/accept.md | 2 +- .../docs/api/basic_json_document/erase.md | 10 +- .../docs/api/basic_json_document/index.md | 2 +- .../docs/api/basic_json_document/insert.md | 20 +- .../docs/api/basic_json_document/load.md | 22 +- .../api/basic_json_document/memory_usage.md | 2 +- .../docs/api/basic_json_document/parse.md | 12 +- .../docs/api/basic_json_document/push_back.md | 22 +- .../docs/api/basic_json_document/read.md | 2 +- .../docs/api/basic_json_document/root.md | 4 +- .../docs/api/basic_json_document/save.md | 16 +- .../docs/api/basic_json_document/set.md | 32 +-- docs/mkdocs/docs/api/basic_json_view/at.md | 10 +- docs/mkdocs/docs/api/basic_json_view/begin.md | 4 +- .../mkdocs/docs/api/basic_json_view/cbegin.md | 2 +- docs/mkdocs/docs/api/basic_json_view/cend.md | 2 +- .../docs/api/basic_json_view/contains.md | 6 +- docs/mkdocs/docs/api/basic_json_view/count.md | 4 +- docs/mkdocs/docs/api/basic_json_view/dump.md | 10 +- docs/mkdocs/docs/api/basic_json_view/empty.md | 2 +- docs/mkdocs/docs/api/basic_json_view/end.md | 2 +- docs/mkdocs/docs/api/basic_json_view/find.md | 6 +- docs/mkdocs/docs/api/basic_json_view/get.md | 22 +- .../docs/api/basic_json_view/get_string.md | 8 +- .../mkdocs/docs/api/basic_json_view/get_to.md | 4 +- docs/mkdocs/docs/api/basic_json_view/index.md | 4 +- .../docs/api/basic_json_view/is_discarded.md | 2 +- docs/mkdocs/docs/api/basic_json_view/items.md | 8 +- .../docs/api/basic_json_view/materialize.md | 4 +- .../docs/api/basic_json_view/number_format.md | 6 +- .../docs/api/basic_json_view/number_token.md | 10 +- .../docs/api/basic_json_view/operator[].md | 18 +- .../docs/api/basic_json_view/operator_eq.md | 6 +- .../docs/api/basic_json_view/operator_ltlt.md | 8 +- .../docs/api/basic_json_view/operator_ne.md | 6 +- docs/mkdocs/docs/api/basic_json_view/size.md | 4 +- .../docs/api/basic_json_view/source_offset.md | 2 +- docs/mkdocs/docs/api/basic_json_view/type.md | 2 +- .../docs/api/basic_json_view/type_name.md | 4 +- docs/mkdocs/docs/api/basic_json_view/value.md | 16 +- .../operator_eq.md | 2 +- .../mkdocs/docs/api/json_editable_document.md | 4 +- docs/mkdocs/docs/api/json_editable_view.md | 4 +- .../macros/json_has_range_view_conversion.md | 2 +- .../docs/api/macros/json_use_simdutf.md | 2 +- docs/mkdocs/docs/api/operator_gtgt.md | 2 +- .../api/ordered_json_editable_document.md | 4 +- docs/mkdocs/docs/api/ordered_map.md | 2 +- docs/mkdocs/docs/css/brand.css | 21 ++ docs/mkdocs/docs/features/arbitrary_types.md | 8 +- docs/mkdocs/docs/features/comments.md | 2 +- docs/mkdocs/docs/features/conversions.md | 8 +- docs/mkdocs/docs/features/index.md | 6 +- docs/mkdocs/docs/features/json_view.md | 64 ++--- docs/mkdocs/docs/features/merge_patch.md | 55 ++++- docs/mkdocs/docs/features/parsing/index.md | 2 +- .../docs/features/parsing/json_lines.md | 2 +- .../docs/features/parsing/parser_callbacks.md | 4 +- .../docs/features/parsing/untrusted_input.md | 18 +- docs/mkdocs/docs/features/performance.md | 36 +-- .../features/types/template_parameters.md | 54 ++--- docs/mkdocs/docs/home/debugging.md | 2 +- docs/mkdocs/docs/home/exceptions.md | 38 +-- docs/mkdocs/docs/home/faq.md | 6 +- docs/mkdocs/docs/home/releases/index.md | 90 +++---- docs/mkdocs/docs/home/sponsors.md | 27 ++- docs/mkdocs/docs/images/release_timeline.svg | 223 +++++++++--------- docs/mkdocs/docs/index.md | 4 +- docs/mkdocs/docs/js/external-links.js | 32 +++ docs/mkdocs/mkdocs.yml | 1 + docs/mkdocs/overrides/home.html | 1 + .../scripts/figures/release_timeline.py | 26 +- 92 files changed, 626 insertions(+), 496 deletions(-) create mode 100644 docs/mkdocs/docs/js/external-links.js diff --git a/docs/mkdocs/docs/api/adl_serializer/from_json.md b/docs/mkdocs/docs/api/adl_serializer/from_json.md index e444bd697..514b96bfd 100644 --- a/docs/mkdocs/docs/api/adl_serializer/from_json.md +++ b/docs/mkdocs/docs/api/adl_serializer/from_json.md @@ -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 diff --git a/docs/mkdocs/docs/api/basic_json/array.md b/docs/mkdocs/docs/api/basic_json/array.md index cbc5a723e..38540be34 100644 --- a/docs/mkdocs/docs/api/basic_json/array.md +++ b/docs/mkdocs/docs/api/basic_json/array.md @@ -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 diff --git a/docs/mkdocs/docs/api/basic_json/basic_json.md b/docs/mkdocs/docs/api/basic_json/basic_json.md index 6a75d0f6a..dadb2d887 100644 --- a/docs/mkdocs/docs/api/basic_json/basic_json.md +++ b/docs/mkdocs/docs/api/basic_json/basic_json.md @@ -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 diff --git a/docs/mkdocs/docs/api/basic_json/binary_t.md b/docs/mkdocs/docs/api/basic_json/binary_t.md index d7a1de92e..493c00414 100644 --- a/docs/mkdocs/docs/api/basic_json/binary_t.md +++ b/docs/mkdocs/docs/api/basic_json/binary_t.md @@ -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` 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. diff --git a/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md b/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md index cd86a98b4..7cc404194 100644 --- a/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md +++ b/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md @@ -43,7 +43,7 @@ store - [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 +- [CBOR](../../features/binary_formats/cbor.md) - the article on the CBOR format ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/empty.md b/docs/mkdocs/docs/api/basic_json/empty.md index fea80f948..06b51932d 100644 --- a/docs/mkdocs/docs/api/basic_json/empty.md +++ b/docs/mkdocs/docs/api/basic_json/empty.md @@ -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 diff --git a/docs/mkdocs/docs/api/basic_json/from_bon8.md b/docs/mkdocs/docs/api/basic_json/from_bon8.md index 2f60c1524..8776e05ac 100644 --- a/docs/mkdocs/docs/api/basic_json/from_bon8.md +++ b/docs/mkdocs/docs/api/basic_json/from_bon8.md @@ -96,7 +96,7 @@ Linear in the size of the input. ## See also -- [`BON8`](../../features/binary_formats/bon8.md) - the format, its byte layout and how values are mapped +- [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 diff --git a/docs/mkdocs/docs/api/basic_json/from_bson.md b/docs/mkdocs/docs/api/basic_json/from_bson.md index fe3ac653f..4d2e7bff9 100644 --- a/docs/mkdocs/docs/api/basic_json/from_bson.md +++ b/docs/mkdocs/docs/api/basic_json/from_bson.md @@ -108,7 +108,7 @@ Linear in the size of the input. ## See also -- [`BSON`](../../features/binary_formats/bson.md) - the format, its byte layout and how values are mapped +- [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 diff --git a/docs/mkdocs/docs/api/basic_json/from_cbor.md b/docs/mkdocs/docs/api/basic_json/from_cbor.md index 97868a798..2d5848a86 100644 --- a/docs/mkdocs/docs/api/basic_json/from_cbor.md +++ b/docs/mkdocs/docs/api/basic_json/from_cbor.md @@ -114,7 +114,7 @@ Linear in the size of the input. ## See also -- [`CBOR`](../../features/binary_formats/cbor.md) - the format, its byte layout and how values are mapped +- [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 diff --git a/docs/mkdocs/docs/api/basic_json/from_ubjson.md b/docs/mkdocs/docs/api/basic_json/from_ubjson.md index 6fbd39aa9..84fd09b2c 100644 --- a/docs/mkdocs/docs/api/basic_json/from_ubjson.md +++ b/docs/mkdocs/docs/api/basic_json/from_ubjson.md @@ -107,7 +107,7 @@ Linear in the size of the input. ## See also -- [`UBJSON`](../../features/binary_formats/ubjson.md) - the format, its byte layout and how values are mapped +- [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 diff --git a/docs/mkdocs/docs/api/basic_json/items.md b/docs/mkdocs/docs/api/basic_json/items.md index 77ca91411..1316826fc 100644 --- a/docs/mkdocs/docs/api/basic_json/items.md +++ b/docs/mkdocs/docs/api/basic_json/items.md @@ -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 diff --git a/docs/mkdocs/docs/api/basic_json/max_size.md b/docs/mkdocs/docs/api/basic_json/max_size.md index e6c819096..39ca2d3f7 100644 --- a/docs/mkdocs/docs/api/basic_json/max_size.md +++ b/docs/mkdocs/docs/api/basic_json/max_size.md @@ -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 diff --git a/docs/mkdocs/docs/api/basic_json/object_t.md b/docs/mkdocs/docs/api/basic_json/object_t.md index 5bdcdb42b..835d7b185 100644 --- a/docs/mkdocs/docs/api/basic_json/object_t.md +++ b/docs/mkdocs/docs/api/basic_json/object_t.md @@ -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. diff --git a/docs/mkdocs/docs/api/basic_json/size.md b/docs/mkdocs/docs/api/basic_json/size.md index 793b08653..5c70d11d0 100644 --- a/docs/mkdocs/docs/api/basic_json/size.md +++ b/docs/mkdocs/docs/api/basic_json/size.md @@ -32,7 +32,7 @@ constant complexity. ## Notes -This function does not return the length of a string stored as JSON value -- it returns the number of elements in the +This function does not return the length of a string stored as JSON value — it returns the number of elements in the JSON value which is `1` in the case of a string. ## Examples diff --git a/docs/mkdocs/docs/api/basic_json/string_t.md b/docs/mkdocs/docs/api/basic_json/string_t.md index 8e1cc7314..1e3a4b2b5 100644 --- a/docs/mkdocs/docs/api/basic_json/string_t.md +++ b/docs/mkdocs/docs/api/basic_json/string_t.md @@ -20,7 +20,7 @@ JSON class into byte-sized characters during deserialization. `StringType` must have a `char`-compatible `value_type`: the library relies on UTF-8/`char`-based storage and processing internally, so `std::wstring`, `std::u16string`, and `std::u32string` are **not** valid choices for - `StringType`. To work with wide-character data, convert it to/from UTF-8 at the boundary instead -- see the + `StringType`. To work with wide-character data, convert it to/from UTF-8 at the boundary instead — see the FAQ's [wide string handling](../../home/faq.md#wide-string-handling) section for a conversion recipe. Beyond the character type, the library expects a substantial part of the `#!cpp std::string` interface (contiguous diff --git a/docs/mkdocs/docs/api/basic_json/to_bon8.md b/docs/mkdocs/docs/api/basic_json/to_bon8.md index 731f24724..6b09bb0d4 100644 --- a/docs/mkdocs/docs/api/basic_json/to_bon8.md +++ b/docs/mkdocs/docs/api/basic_json/to_bon8.md @@ -82,7 +82,7 @@ Linear in the size of the JSON value `j`. ## See also -- [`BON8`](../../features/binary_formats/bon8.md) - the format, its byte layout and how values are mapped +- [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 - [`from_bon8`](from_bon8.md) - create a JSON value from an input in BON8 format - [`to_cbor`](to_cbor.md) - create a CBOR serialization of a JSON value diff --git a/docs/mkdocs/docs/api/basic_json/to_bson.md b/docs/mkdocs/docs/api/basic_json/to_bson.md index 91ee8e4ab..37df4c9ea 100644 --- a/docs/mkdocs/docs/api/basic_json/to_bson.md +++ b/docs/mkdocs/docs/api/basic_json/to_bson.md @@ -104,7 +104,7 @@ pass before anything is written. ## See also -- [`BSON`](../../features/binary_formats/bson.md) - the format, its byte layout and how values are mapped +- [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 - [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled - [`from_bson`](from_bson.md) - create a JSON value from an input in BSON format diff --git a/docs/mkdocs/docs/api/basic_json/to_cbor.md b/docs/mkdocs/docs/api/basic_json/to_cbor.md index 31e5db6af..f1d7b8858 100644 --- a/docs/mkdocs/docs/api/basic_json/to_cbor.md +++ b/docs/mkdocs/docs/api/basic_json/to_cbor.md @@ -77,7 +77,7 @@ Linear in the size of the JSON value `j`. ## See also -- [`CBOR`](../../features/binary_formats/cbor.md) - the format, its byte layout and how values are mapped +- [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 - [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled - [`from_cbor`](from_cbor.md) - create a JSON value from an input in CBOR format diff --git a/docs/mkdocs/docs/api/basic_json/to_ubjson.md b/docs/mkdocs/docs/api/basic_json/to_ubjson.md index d2267b2c8..345743e03 100644 --- a/docs/mkdocs/docs/api/basic_json/to_ubjson.md +++ b/docs/mkdocs/docs/api/basic_json/to_ubjson.md @@ -101,7 +101,7 @@ Linear in the size of the JSON value `j`. ## See also -- [`UBJSON`](../../features/binary_formats/ubjson.md) - the format, its byte layout and how values are mapped +- [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 - [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled - [`from_ubjson`](from_ubjson.md) - create a JSON value from an input in UBJSON format diff --git a/docs/mkdocs/docs/api/basic_json/type_name.md b/docs/mkdocs/docs/api/basic_json/type_name.md index 40e541c7a..7af96acfa 100644 --- a/docs/mkdocs/docs/api/basic_json/type_name.md +++ b/docs/mkdocs/docs/api/basic_json/type_name.md @@ -4,7 +4,7 @@ const char* type_name() const noexcept; ``` -Returns the type name as string to be used in error messages -- usually to indicate that a function was called on a +Returns the type name as string to be used in error messages — usually to indicate that a function was called on a wrong JSON type. ## Return value diff --git a/docs/mkdocs/docs/api/basic_json_document/accept.md b/docs/mkdocs/docs/api/basic_json_document/accept.md index 65436e5c3..1f1070d51 100644 --- a/docs/mkdocs/docs/api/basic_json_document/accept.md +++ b/docs/mkdocs/docs/api/basic_json_document/accept.md @@ -9,7 +9,7 @@ static bool accept(InputType&& input, Checks whether the input is valid JSON, accepting and rejecting exactly what [`BasicJsonType::accept()`](../basic_json/accept.md) does, with the same options. Unlike [`parse()`](parse.md), this -function never throws an exception for invalid input, and the returned `#!cpp bool` is the only result -- no document +function never throws an exception for invalid input, and the returned `#!cpp bool` is the only result — no document is returned. The result is the same as that of `BasicJsonType::accept()` by design; the difference is how the check is made. This diff --git a/docs/mkdocs/docs/api/basic_json_document/erase.md b/docs/mkdocs/docs/api/basic_json_document/erase.md index 43458b9c5..e585900c6 100644 --- a/docs/mkdocs/docs/api/basic_json_document/erase.md +++ b/docs/mkdocs/docs/api/basic_json_document/erase.md @@ -54,7 +54,7 @@ has `erase`; calling it on a read-only `basic_json_document` fails to compile (` ## Exceptions -1. Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) if `object` is not an object -- the +1. Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) if `object` is not an object — the same message [`BasicJsonType::erase`](../basic_json/erase.md) throws for the same type. 2. Throws `type_error.307` if `array` is not an array. Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if `idx` is negative, or if @@ -86,12 +86,12 @@ always starts from this document's own [`root()`](root.md). !!! info "Duplicate keys" - Overload 1. removes *every* member with `key`, not just the first -- unlike [`set`](set.md), which assigns the + Overload 1. removes *every* member with `key`, not just the first — unlike [`set`](set.md), which assigns the first occurrence and drops the rest. This is why it returns a count rather than a single view: there may be more than one member removed, or none. Like [`set`](set.md) and [`push_back`](push_back.md), `erase` never moves an element's *value*: a view still -referring to a removed member or element keeps showing what it last held (see [Edits](index.md#edits)) -- it just no +referring to a removed member or element keeps showing what it last held (see [Edits](index.md#edits)) — it just no longer appears when `array`/`object` is read, dumped, or iterated. What does change is the container's sequence of *links* to its elements: removing an element of `array` (2.) shifts the links to the elements after it by one, as [`insert`](insert.md) does in the other direction. *Every* iterator already taken over `array`/`object` is invalidated @@ -101,8 +101,8 @@ by an erase, not only those at or after the removed element, since the container ??? example - The example below drops a deprecated field and a decommissioned entry from a configuration document -- using all - three overloads -- and shows what stays intact that would not with a plain `json`/`ordered_json` value: the order + The example below drops a deprecated field and a decommissioned entry from a configuration document — using all + three overloads — and shows what stays intact that would not with a plain `json`/`ordered_json` value: the order of the fields around the ones removed, and the exact spelling of a number that was never touched. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_document/index.md b/docs/mkdocs/docs/api/basic_json_document/index.md index daa7d64b8..4f4e27cb9 100644 --- a/docs/mkdocs/docs/api/basic_json_document/index.md +++ b/docs/mkdocs/docs/api/basic_json_document/index.md @@ -108,7 +108,7 @@ points apply to every edit: anything `BasicJsonType` can be constructed from (numbers, strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...). - [`dump()`](../basic_json_view/dump.md) writes an edited document with members in document order, new members at the end, and, with [`number_format::source`](../basic_json_view/number_format.md), keeps the spelling of every - number that was not itself edited -- see [Editing a document](../../features/json_view.md#editing-a-document) for + number that was not itself edited — see [Editing a document](../../features/json_view.md#editing-a-document) for why this matters. - [`read()`](read.md) discards all edits, [`shrink_to_fit()`](shrink_to_fit.md) does not move the node index once there are edits, and [`memory_usage()`](memory_usage.md) includes the memory edits use. diff --git a/docs/mkdocs/docs/api/basic_json_document/insert.md b/docs/mkdocs/docs/api/basic_json_document/insert.md index a406487d9..23b04535c 100644 --- a/docs/mkdocs/docs/api/basic_json_document/insert.md +++ b/docs/mkdocs/docs/api/basic_json_document/insert.md @@ -13,8 +13,8 @@ Inserts `value` into `array` as a new element before position `idx`, which must [`push_back`](push_back.md), a [null](../basic_json_view/is_null.md) `array` does *not* first become an empty array: `array` must already be an array. -`value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any* document -- read-only or -editable, and it does not have to be `array`'s own document -- which is copied so that nothing is shared with the +`value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any* document — read-only or +editable, and it does not have to be `array`'s own document — which is copied so that nothing is shared with the source document afterward; a `BasicJsonType` value; or anything `BasicJsonType` can be constructed from (numbers, strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...). @@ -44,16 +44,16 @@ a view of the new element, now holding `value` ## Exception safety -Basic exception safety: `value` is fully encoded -- including the checks below -- into storage owned by the document +Basic exception safety: `value` is fully encoded — including the checks below — into storage owned by the document before anything already reachable from [`root()`](root.md) is touched, so a failure while encoding `value` (an invalid argument, or `#!cpp std::bad_alloc`) leaves the document completely unchanged, other than memory allocated -for the encoding that is not reclaimed. A failure of a later allocation -- while `array` switches from its parsed -layout to a growable block, or while that block grows, see [Notes](#notes) -- can still leave `array` already +for the encoding that is not reclaimed. A failure of a later allocation — while `array` switches from its parsed +layout to a growable block, or while that block grows, see [Notes](#notes) — can still leave `array` already switched to that layout even though `value` itself was not inserted. ## Exceptions -Throws [`type_error.309`](../../home/exceptions.md#jsonexceptiontype_error309) if `array` is not an array -- the same +Throws [`type_error.309`](../../home/exceptions.md#jsonexceptiontype_error309) if `array` is not an array — the same message [`BasicJsonType::insert`](../basic_json/insert.md) throws for the same type; a null `array` throws this too (see above). Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if `idx` is negative, or if `#!cpp idx > array.size()`. Throws @@ -62,7 +62,7 @@ document") if `array` is a [discarded](../basic_json_view/is_discarded.md) view Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `value` is a [discarded](../basic_json_view/is_discarded.md) view or a [discarded](../basic_json/is_discarded.md) `BasicJsonType` value, and [`type_error.319`](../../home/exceptions.md#jsonexceptiontype_error319) if `value` is (or contains) a -binary value -- `BasicJsonType` can hold one, but a `json_document` cannot. Throws +binary value — `BasicJsonType` can hold one, but a `json_document` cannot. Throws [`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316) if `value` is (or contains) a string that is not valid UTF-8, with the same message [`BasicJsonType::dump()`](../basic_json/dump.md) gives for that string. @@ -76,8 +76,8 @@ grows in amortized constant time; inserting before the end within that block sti ## Notes -Like [`set`](set.md) on a member or an element, `insert` never moves an existing *element's value* -- only where -`array`'s *links* to its elements live -- so a view of an existing element of `array` stays valid across an +Like [`set`](set.md) on a member or an element, `insert` never moves an existing *element's value* — only where +`array`'s *links* to its elements live — so a view of an existing element of `array` stays valid across an `insert`, and keeps referring to the same element even though its index shifts. Any iterator already taken over `array` is invalidated, since it was walking the old layout. See [Edits](index.md#edits) for what stays valid across an edit in general. @@ -88,7 +88,7 @@ an edit in general. The example below inserts a step into the middle of a deployment plan, without touching the steps that come after it, and shows that a view taken before the insert keeps referring to the same element even though its - index shifts -- something a plain `json`/`ordered_json` array, or its `std::vector`-based storage, has no + index shifts — something a plain `json`/`ordered_json` array, or its `std::vector`-based storage, has no equivalent for. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_document/load.md b/docs/mkdocs/docs/api/basic_json_document/load.md index 46a657caf..4ac9a2b6b 100644 --- a/docs/mkdocs/docs/api/basic_json_document/load.md +++ b/docs/mkdocs/docs/api/basic_json_document/load.md @@ -16,14 +16,14 @@ static basic_json_document load(std::vector&& image, 1. Reads an image [`save()`](save.md) wrote, from a pointer and a byte count. The image is **borrowed**: `image` must stay alive and unchanged for as long as the returned document, and any view taken from it, is used. -2. Reads an image from a `#!cpp std::vector`. Also **borrowed** -- equivalent to overload 1 called with +2. Reads an image from a `#!cpp std::vector`. Also **borrowed** — equivalent to overload 1 called with `#!cpp image.data()` and `#!cpp image.size()`. 3. Reads an image, keeping the vector instead of copying it: `image` is moved into the document (no copy), which then owns it for as long as it needs the text and the decoded strings. [`owns_source()`](owns_source.md) is `#!cpp true` afterward. -In every overload, the node index is copied into storage the document itself owns -- so that it is properly aligned, -and, for an [editable](index.md#edits) document, can be edited -- while the text and the decoded strings stay in +In every overload, the node index is copied into storage the document itself owns — so that it is properly aligned, +and, for an [editable](index.md#edits) document, can be edited — while the text and the decoded strings stay in `image`. The hash indexes [large objects](../../features/json_view.md) use for lookup are rebuilt, exactly as after parsing. @@ -49,13 +49,13 @@ Overloads 1 and 2 give the strong guarantee: `image` is only read, never written caller's buffer untouched. Overload 3 moves `image` into the document *before* validating it, so that a good image is kept without a copy. If -loading then fails, the partially built document -- and the vector now inside it -- is discarded along with the +loading then fails, the partially built document — and the vector now inside it — is discarded along with the exception, and `image` itself is left **empty**, not restored to what was passed in. Move a copy in instead, or validate with overload 2 first, if the original vector must survive a failed load. ## Exceptions -On a big-endian target, throws [`type_error.320`](../../home/exceptions.md#jsonexceptiontype_error320) -- the same +On a big-endian target, throws [`type_error.320`](../../home/exceptions.md#jsonexceptiontype_error320) — the same exception [`save()`](save.md#exceptions) throws there, since the image format is little-endian only. Otherwise throws [`parse_error.116`](../../home/exceptions.md#jsonexceptionparse_error116) if `image` is not one @@ -66,7 +66,7 @@ Otherwise throws [`parse_error.116`](../../home/exceptions.md#jsonexceptionparse | `too short` | `image` is `#!cpp nullptr`, or `size` is smaller than the 64-byte header | | `unknown format` | the header's magic bytes or version do not match, or a reserved header field is not zero | | `sizes out of range` | the node count, text size, or decoded-string size the header describes does not fit `size`, or the `#!cpp '\0'` after the text or after the decoded strings is missing | -| `the check failed` | `check` is not `#!cpp image_check::none`, and the image fails it -- see [`image_check`](#image_check) | +| `the check failed` | `check` is not `#!cpp image_check::none`, and the image fails it — see [`image_check`](#image_check) | !!! failure "Example messages" @@ -116,7 +116,7 @@ How thoroughly `load()` validates `image` before trusting it. token is well-formed and matches the value stored for it. Strings and float tokens may share a range only if the ranges are identical (as nodes that share a value do), and never overlap otherwise. Reading and serializing a checked image is safe and always produces valid JSON, exactly as for a parsed document. This is the right choice for - an image from anything you do not fully control -- a file, a cache shared with other processes, a peer on the + an image from anything you do not fully control — a file, a cache shared with other processes, a peer on the network. `bounds` @@ -136,7 +136,7 @@ How thoroughly `load()` validates `image` before trusting it. your own memory. **Lifetime.** Overloads 1 and 2 borrow `image`: it must stay alive and byte-for-byte unchanged for as long as the -returned document, and any [view](../basic_json_view/index.md) taken from it, is used -- exactly like a document +returned document, and any [view](../basic_json_view/index.md) taken from it, is used — exactly like a document [`parse()`](parse.md) borrowed its input for. Overload 3 avoids this by keeping the vector itself; see [`owns_source`](owns_source.md). @@ -145,7 +145,7 @@ returned document, and any [view](../basic_json_view/index.md) taken from it, is The image format is versioned but not yet stable, and may change in an incompatible way before it is declared stable; `load()` already rejects an image written by a different format version with `parse_error.116` ("unknown format"). Use images to cache a document within one build of the library, or to hand one to another - process running the *same* build on the *same* (little-endian) machine -- not as a long-term storage format. + process running the *same* build on the *same* (little-endian) machine — not as a long-term storage format. ## Examples @@ -154,8 +154,8 @@ returned document, and any [view](../basic_json_view/index.md) taken from it, is The example below saves a parsed document as an image, checks that `load()` reproduces the original [`dump()`](../basic_json_view/dump.md) without parsing, and shows the difference between `load(std::move(image))` (owned) and `load(image)` (borrowed). It then damages one byte of the image and shows - `image_check::full` rejecting it with `parse_error.116`, while `image_check::bounds` -- meant for a cache the - process already trusts -- still reads it without going out of bounds. + `image_check::full` rejecting it with `parse_error.116`, while `image_check::bounds` — meant for a cache the + process already trusts — still reads it without going out of bounds. ```cpp --8<-- "examples/basic_json_document__load.cpp" diff --git a/docs/mkdocs/docs/api/basic_json_document/memory_usage.md b/docs/mkdocs/docs/api/basic_json_document/memory_usage.md index 22828dd94..d265d623c 100644 --- a/docs/mkdocs/docs/api/basic_json_document/memory_usage.md +++ b/docs/mkdocs/docs/api/basic_json_document/memory_usage.md @@ -23,7 +23,7 @@ Constant. The exact value depends on the platform, the allocator, and the library's own layout, and may change between versions; do not rely on it being a specific number, and do not compare it across different builds or platforms. -Compare it for the same document over time, or between documents built with the same binary, instead -- for instance +Compare it for the same document over time, or between documents built with the same binary, instead — for instance to observe the effect of [`shrink_to_fit()`](shrink_to_fit.md). ## Examples diff --git a/docs/mkdocs/docs/api/basic_json_document/parse.md b/docs/mkdocs/docs/api/basic_json_document/parse.md index da58a98bb..e458e621d 100644 --- a/docs/mkdocs/docs/api/basic_json_document/parse.md +++ b/docs/mkdocs/docs/api/basic_json_document/parse.md @@ -24,7 +24,7 @@ Both overloads accept the same JSON text as [`BasicJsonType::parse()`](../basic_ the input) instead of a tree of `BasicJsonType` values. They accept every input `BasicJsonType::parse()` takes, and in addition a pointer to a null-terminated wide string (which `BasicJsonType::parse()` rejects). Contiguous inputs of single-byte characters that stay alive can be borrowed; all others (streams, `#!cpp FILE*`, wide characters, which -must be converted to UTF-8, and non-contiguous iterators) are read into a copy that the document owns -- see the +must be converted to UTF-8, and non-contiguous iterators) are read into a copy that the document owns — see the Notes. Use [`parse_copy()`](parse_copy.md) to get an owned copy of a borrowable input as well. @@ -82,8 +82,8 @@ discarded; see [`is_discarded`](is_discarded.md). ## Exceptions -Throws the same exception [`BasicJsonType::parse()`](../basic_json/parse.md) throws for the same input and options -- -the same exception id, message, and position -- because on a failing input the library's own parser is run on the +Throws the same exception [`BasicJsonType::parse()`](../basic_json/parse.md) throws for the same input and options — +the same exception id, message, and position — because on a failing input the library's own parser is run on the same bytes to produce the diagnostic. This replay runs only for a failing input, and costs about a lexing pass up to the error (its SAX handler builds no values); with `allow_exceptions` set to `#!cpp false`, it is skipped and a discarded document is returned instead. Additionally throws @@ -100,7 +100,7 @@ Linear in the length of the input. | `input` | ownership | |--------------------------------------------------------------------------------------|--------------------------------------------------------------| -| lvalue byte container (`std::string`, `std::vector`, ...), `std::string_view`, C string, character array | **borrowed** -- `input` must outlive the document | +| lvalue byte container (`std::string`, `std::vector`, ...), `std::string_view`, C string, character array | **borrowed** — `input` must outlive the document | | non-const rvalue `#!cpp std::string` | **owned**, moved in without a copy | | other rvalue byte container (including a `#!cpp const` rvalue `#!cpp std::string`) | **owned**, copied | | stream, `#!cpp FILE*`, wide characters, or anything else read through the general input adapter | **owned**, read into a buffer (a stream is read to its end) | @@ -117,8 +117,8 @@ See [`owns_source`](owns_source.md) to check which happened after a call, and th **Numbers.** As for [`BasicJsonType::parse()`](../basic_json/parse.md), an integer literal too large for the 64-bit integer type becomes a floating-point value. -**No lengths.** An integer argument that is not a `#!cpp bool` where the flags are expected -- for example -`#!cpp parse(ptr, len)` -- does not compile (the overload is deleted). Such a call would convert `len` to +**No lengths.** An integer argument that is not a `#!cpp bool` where the flags are expected — for example +`#!cpp parse(ptr, len)` — does not compile (the overload is deleted). Such a call would convert `len` to `allow_exceptions` and read `ptr` as a null-terminated string, past the end of a buffer that has none. To parse a buffer of a given length, pass a pair of pointers: `#!cpp parse(ptr, ptr + len)`. The same holds for [`parse_copy`](parse_copy.md), [`accept`](accept.md), and [`read`](read.md). diff --git a/docs/mkdocs/docs/api/basic_json_document/push_back.md b/docs/mkdocs/docs/api/basic_json_document/push_back.md index bc23bfd4c..059ed645c 100644 --- a/docs/mkdocs/docs/api/basic_json_document/push_back.md +++ b/docs/mkdocs/docs/api/basic_json_document/push_back.md @@ -8,8 +8,8 @@ view_type push_back(view_type array, V&& value); Appends `value` as a new last element of `array`. A [null](../basic_json_view/is_null.md) `array` first becomes an empty array, the same way [`set`](set.md) turns a null `object` into an empty object. -`value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any* document -- read-only or -editable, and it does not have to be `array`'s own document -- which is copied so that nothing is shared with the +`value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any* document — read-only or +editable, and it does not have to be `array`'s own document — which is copied so that nothing is shared with the source document afterward; a `BasicJsonType` value; or anything `BasicJsonType` can be constructed from (numbers, strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...). @@ -35,23 +35,23 @@ a view of the new last element of `array`, now holding `value` ## Exception safety -Basic exception safety: `value` is fully encoded -- including the checks below -- into storage owned by the document +Basic exception safety: `value` is fully encoded — including the checks below — into storage owned by the document before anything already reachable from [`root()`](root.md) is touched, so a failure while encoding `value` (an invalid argument, or `#!cpp std::bad_alloc`) leaves the document completely unchanged, other than memory allocated -for the encoding that is not reclaimed. A failure of a later allocation -- while `array` switches from its parsed -layout to a growable block, or while that block grows, see [Notes](#notes) -- can still leave a partial effect, such +for the encoding that is not reclaimed. A failure of a later allocation — while `array` switches from its parsed +layout to a growable block, or while that block grows, see [Notes](#notes) — can still leave a partial effect, such as a null `array` argument already turned into an empty array even though `value` itself was not appended. ## Exceptions Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) if `array` is neither an array nor -null -- the same message [`BasicJsonType::push_back`](../basic_json/push_back.md) throws for the same type. Throws +null — the same message [`BasicJsonType::push_back`](../basic_json/push_back.md) throws for the same type. Throws [`invalid_iterator.202`](../../home/exceptions.md#jsonexceptioninvalid_iterator202) ("view does not belong to this document") if `array` is a [discarded](../basic_json_view/is_discarded.md) view or a view of a *different* document. Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `value` is a [discarded](../basic_json_view/is_discarded.md) view or a [discarded](../basic_json/is_discarded.md) `BasicJsonType` value, and [`type_error.319`](../../home/exceptions.md#jsonexceptiontype_error319) if `value` is (or contains) a -binary value -- `BasicJsonType` can hold one, but a `json_document` cannot. Throws +binary value — `BasicJsonType` can hold one, but a `json_document` cannot. Throws [`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316) if `value` is (or contains) a string that is not valid UTF-8, with the same message [`BasicJsonType::dump()`](../basic_json/dump.md) gives for that string. @@ -59,14 +59,14 @@ not valid UTF-8, with the same message [`BasicJsonType::dump()`](../basic_json/d Amortized constant, plus time linear in the size of `value` to encode it into the document's storage (constant for a scalar, linear in the number of nested values for an array or object): the elements of `array` move to a growable -block of links the first time it is appended to (or [`set`](set.md) on), and that block itself grows -- doubling its -capacity, so the cost of growing it amortizes to constant per element -- only once it runs out of room. See +block of links the first time it is appended to (or [`set`](set.md) on), and that block itself grows — doubling its +capacity, so the cost of growing it amortizes to constant per element — only once it runs out of room. See [Notes](#notes). ## Notes -Like [`set`](set.md) on a member or an element, `push_back` never moves an existing element itself -- only where -`array`'s *links* to its elements live -- so a view of an existing element of `array` stays valid across a +Like [`set`](set.md) on a member or an element, `push_back` never moves an existing element itself — only where +`array`'s *links* to its elements live — so a view of an existing element of `array` stays valid across a `push_back`, but any iterator already taken over `array` is invalidated, since it was walking the old layout. See [Edits](index.md#edits) for what stays valid across an edit in general. diff --git a/docs/mkdocs/docs/api/basic_json_document/read.md b/docs/mkdocs/docs/api/basic_json_document/read.md index 4086f24dd..63915b1c2 100644 --- a/docs/mkdocs/docs/api/basic_json_document/read.md +++ b/docs/mkdocs/docs/api/basic_json_document/read.md @@ -43,7 +43,7 @@ Linear in the length of the input. ## Notes -Every view taken from `#!cpp *this` before the call -- including the previous [`root()`](root.md) -- is invalidated, +Every view taken from `#!cpp *this` before the call — including the previous [`root()`](root.md) — is invalidated, whether or not the new parse succeeds; take fresh views from [`root()`](root.md) afterward. `input` is borrowed or owned by the same rules as [`parse()`](parse.md#notes); a document can borrow on one call and diff --git a/docs/mkdocs/docs/api/basic_json_document/root.md b/docs/mkdocs/docs/api/basic_json_document/root.md index b6a86797b..14e4514c2 100644 --- a/docs/mkdocs/docs/api/basic_json_document/root.md +++ b/docs/mkdocs/docs/api/basic_json_document/root.md @@ -37,8 +37,8 @@ auto v = doc.root(); ``` `root()` is a cheap handle into the document's index, not a copy of anything; call it as often as needed. The -returned view is valid under the same conditions as any other view of the document -- see -[Object inspection](../basic_json_view/index.md) -- in particular, it is invalidated by the next +returned view is valid under the same conditions as any other view of the document — see +[Object inspection](../basic_json_view/index.md) — in particular, it is invalidated by the next [`read()`](read.md) or [`shrink_to_fit()`](shrink_to_fit.md) on this document. A view can dangle, like a `#!cpp std::string_view`; see [Ownership and lifetime](../../features/json_view.md#ownership-and-lifetime). diff --git a/docs/mkdocs/docs/api/basic_json_document/save.md b/docs/mkdocs/docs/api/basic_json_document/save.md index 5b455be31..e20712b28 100644 --- a/docs/mkdocs/docs/api/basic_json_document/save.md +++ b/docs/mkdocs/docs/api/basic_json_document/save.md @@ -6,13 +6,13 @@ std::vector save() const; Writes the document as an *image*: a byte buffer that [`load`](load.md) reads back without parsing. The image holds the node index, the source text (plus, for an edited document, the number tokens edits wrote), and the decoded -strings (plus the strings edits wrote) -- everything [`root()`](root.md) needs, with nothing left to parse. +strings (plus the strings edits wrote) — everything [`root()`](root.md) needs, with nothing left to parse. An edited document is written in its *current* state, with its values in document order, the way the library's own parser would have produced them for that JSON text: a member [`set`](set.md) added goes at the end, an [`erase`](erase.md)d member leaves no trace, and a float that is not finite (NaN or positive/negative infinity) becomes null, the same substitution [`dump()`](../basic_json_view/dump.md) makes. The same document always saves to -the same bytes -- also across `BasicJsonType` and `#!cpp Editable`, since the image reflects document order and +the same bytes — also across `BasicJsonType` and `#!cpp Editable`, since the image reflects document order and values only, not which specialization produced them. ## Return value @@ -28,14 +28,14 @@ exactly as it was, and the partially built image is discarded with the exception ## Exceptions Throws [`type_error.320`](../../home/exceptions.md#jsonexceptiontype_error320) if the document is -[discarded](is_discarded.md) -- a default-constructed document, or one a failed [`parse()`](parse.md)/ +[discarded](is_discarded.md) — a default-constructed document, or one a failed [`parse()`](parse.md)/ [`read()`](read.md) with `allow_exceptions == false` left discarded. On a big-endian target, throws `type_error.320` with a different message instead: the image format is little-endian only (see [Notes](#notes)). Throws [`out_of_range.416`](../../home/exceptions.md#jsonexceptionout_of_range416) if the node count, the text, or -the decoded strings of the image would individually reach 4 GiB -- the same 32-bit offsets +the decoded strings of the image would individually reach 4 GiB — the same 32-bit offsets [`parse()`](parse.md#exceptions) and, for edits, [`set`](set.md)/[`push_back`](push_back.md) are already limited to. !!! failure "Example messages" @@ -61,13 +61,13 @@ up in the image. and the sizes of the text and the decoded strings, all little-endian), followed by the nodes ([16 bytes each](../../home/architecture.md#node-index-of-json-views)), the text and a `#!cpp '\0'`, and the decoded strings and a `#!cpp '\0'`. [`load`](load.md) checks the header, and the sizes it describes, before reading anything -else -- see [`load`'s Exceptions](load.md#exceptions). +else — see [`load`'s Exceptions](load.md#exceptions). !!! warning "Experimental" The image format is versioned but not yet stable: it may change in an incompatible way before it is declared stable. Use images to cache a document within one build of the library, or to hand one to another process running - the *same* build on the *same* (little-endian) machine -- not as a long-term storage format. Keep the original + the *same* build on the *same* (little-endian) machine — not as a long-term storage format. Keep the original JSON text if you need to read a saved document back with a future library version. **Little-endian only.** The image is written as raw little-endian bytes, with no byte-swapping. `save()` (and @@ -78,8 +78,8 @@ reader could not interpret correctly. ??? example "Caching a parsed document as an image" - The example below saves a parsed configuration as an image -- the way a service might cache one to answer later - requests without parsing the text again -- and confirms that loading it back gives exactly the same result as + The example below saves a parsed configuration as an image — the way a service might cache one to answer later + requests without parsing the text again — and confirms that loading it back gives exactly the same result as parsing did, and that saving is deterministic. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_document/set.md b/docs/mkdocs/docs/api/basic_json_document/set.md index f227bf42c..850d550c3 100644 --- a/docs/mkdocs/docs/api/basic_json_document/set.md +++ b/docs/mkdocs/docs/api/basic_json_document/set.md @@ -23,8 +23,8 @@ has `set`; calling it on a read-only `basic_json_document` fails to compile (`#! 1. Replaces the value `target` refers to with `value`. 2. Sets the member `key` of the object `object` to `value`: assigns it if `object` already has a member with this - key -- the first one, should the key occur more than once, and the later duplicates are then dropped (see the - [Notes](#notes) below) -- or appends a new member at the end otherwise. A [null](../basic_json_view/is_null.md) + key — the first one, should the key occur more than once, and the later duplicates are then dropped (see the + [Notes](#notes) below) — or appends a new member at the end otherwise. A [null](../basic_json_view/is_null.md) `object` first becomes an empty object. 3. Assigns `value` to the element at index `idx` of the array `array`, which must already exist (`#!cpp idx < array.size()`). @@ -37,7 +37,7 @@ has `set`; calling it on a read-only `basic_json_document` fails to compile (`#! null values up to that index), an object otherwise. An empty `ptr` sets [`root()`](root.md) itself, as in 1. In every overload, `value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any* -document -- read-only or editable, and it does not have to be `target`'s/`object`'s/`array`'s own document -- which +document — read-only or editable, and it does not have to be `target`'s/`object`'s/`array`'s own document — which is copied so that nothing is shared with the source document afterward; a `BasicJsonType` value; or anything `BasicJsonType` can be constructed from (numbers, strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...). @@ -82,11 +82,11 @@ is copied so that nothing is shared with the source document afterward; a `Basic ## Exception safety -Basic exception safety: `value` is fully encoded -- including the checks below -- into storage owned by the document +Basic exception safety: `value` is fully encoded — including the checks below — into storage owned by the document before anything already reachable from [`root()`](root.md) is touched, so a failure while encoding `value` (an invalid argument, or `#!cpp std::bad_alloc`) leaves the document completely unchanged, other than memory allocated -for the encoding that is not reclaimed. A failure of a later allocation -- while an edited array or object switches -from its parsed layout to a growable block, see [Notes](#notes) -- can still leave a partial effect, such as a +for the encoding that is not reclaimed. A failure of a later allocation — while an edited array or object switches +from its parsed layout to a growable block, see [Notes](#notes) — can still leave a partial effect, such as a [null](../basic_json_view/is_null.md) `object`/`array` argument already turned into an empty object/array even though `value` itself was not linked in. Likewise, a failure of `value` in 4. leaves a null parent that is set with an index beyond 0 already filled with the null values before the index. @@ -95,14 +95,14 @@ index beyond 0 already filled with the null values before the index. 1. Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `value` is a [discarded](../basic_json_view/is_discarded.md) view, or a [discarded](../basic_json/is_discarded.md) - `BasicJsonType` value (e.g. `#!cpp BasicJsonType(value_t::discarded)`) -- an object or array `value`, of either + `BasicJsonType` value (e.g. `#!cpp BasicJsonType(value_t::discarded)`) — an object or array `value`, of either kind, is fine and is encoded as a whole subtree. 2. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if `object` is neither an object - nor null -- the same message [`operator[]`](../basic_json_view/operator%5B%5D.md) throws for a string argument on + nor null — the same message [`operator[]`](../basic_json_view/operator%5B%5D.md) throws for a string argument on such a value. Throws [`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316) if `key` is not valid UTF-8, with the same message [`BasicJsonType::dump()`](../basic_json/dump.md) gives for that string. Also throws what 1. throws for `value`. -3. Throws `type_error.305` if `array` is not an array -- the same message `operator[]` throws for a numeric argument +3. Throws `type_error.305` if `array` is not an array — the same message `operator[]` throws for a numeric argument on such a value. Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if `idx` is negative, or if `#!cpp idx >= array.size()`. Also throws what 1. throws for `value`. 4. Throws what [`at`](../basic_json_view/at.md) throws (overload 3) for resolving `ptr`'s parent, except that a @@ -121,7 +121,7 @@ index beyond 0 already filled with the null values before the index. Also throws what 1. throws for `value`. Every overload also throws [`type_error.319`](../../home/exceptions.md#jsonexceptiontype_error319) if `value` is (or -contains) a binary value -- `BasicJsonType` can hold one, but a `json_document` cannot -- and +contains) a binary value — `BasicJsonType` can hold one, but a `json_document` cannot — and [`invalid_iterator.202`](../../home/exceptions.md#jsonexceptioninvalid_iterator202) ("view does not belong to this document") if `target`/`object`/`array` is a [discarded](../basic_json_view/is_discarded.md) view or a view of a *different* document (overloads 1-3 only; overload 4 always starts from this document's own [`root()`](root.md)). @@ -132,7 +132,7 @@ document") if `target`/`object`/`array` is a [discarded](../basic_json_view/is_d number of nested values for an array or object. If `target` is itself an array or object that spans more than one node in its parent's original, unedited layout, and `value` is a scalar, replacing it additionally costs time linear in the size of the document, the *first* time (the parent of `target` is looked up from - [`root()`](root.md), and then switches to links) -- see [Notes](#notes). Once the parent has links, `target` is + [`root()`](root.md), and then switches to links) — see [Notes](#notes). Once the parent has links, `target` is replaced in constant time: setting every element of a large array one after the other is linear overall. To avoid the lookup altogether, use 3. (or 2. for an object), which know the parent. 2. Linear in the number of members of `object`, to find an existing member with `key`, plus the complexity of 1. for @@ -147,7 +147,7 @@ document") if `target`/`object`/`array` is a [discarded](../basic_json_view/is_d !!! info "Duplicate keys" If `object` already has more than one member with `key` (2.), the *first* one is assigned `value` and every - later member with the same key is removed -- so that a lookup, an iteration, and + later member with the same key is removed — so that a lookup, an iteration, and [`materialize()`](../basic_json_view/materialize.md) of `object` afterward all agree on a single value for `key`, the same way [`operator[]`](../basic_json_view/operator%5B%5D.md) already picks the first occurrence of a duplicate key for reading. See the [Notes on duplicate keys](../basic_json_view/operator%5B%5D.md#notes) of @@ -156,8 +156,8 @@ document") if `target`/`object`/`array` is a [discarded](../basic_json_view/is_d Setting a member (2.) or an element (3., through 4.) of an array or object whose elements have not been edited before switches it from its parsed layout to a growable block holding links to its elements; a later [`push_back`](push_back.md) or `set` on the same container reuses that block, growing it (amortized constant time) -only once it runs out of room. This never moves an element itself -- only where the container's *links* to its -elements live -- so a view of an element stays valid, but any iterator already taken over the container is +only once it runs out of room. This never moves an element itself — only where the container's *links* to its +elements live — so a view of an element stays valid, but any iterator already taken over the container is invalidated, since it was walking the old layout. See [Edits](index.md#edits) for what stays valid across an edit in general. @@ -170,8 +170,8 @@ one-node scalar. ??? example "Example: (1)/(2)/(3)/(4) replace a value, set a member, assign an element, set via a JSON pointer" - The example below edits a small configuration document -- replacing a value, adding an object member, assigning - an array element, and reaching a field through a JSON pointer -- and shows what + The example below edits a small configuration document — replacing a value, adding an object member, assigning + an array element, and reaching a field through a JSON pointer — and shows what [`dump()`](../basic_json_view/dump.md) preserves that is lost once the same edits are made on a `BasicJsonType` value instead: the order object members were written in, and the exact spelling of a number that was never touched. diff --git a/docs/mkdocs/docs/api/basic_json_view/at.md b/docs/mkdocs/docs/api/basic_json_view/at.md index 45b198b95..747b46299 100644 --- a/docs/mkdocs/docs/api/basic_json_view/at.md +++ b/docs/mkdocs/docs/api/basic_json_view/at.md @@ -15,7 +15,7 @@ basic_json_view at(IntegerType idx) const; basic_json_view at(const json_pointer& ptr) const; ``` -1. Returns the value of the object member with key `key` -- the first one, should the key occur more than once (see +1. Returns the value of the object member with key `key` — the first one, should the key occur more than once (see [Notes on duplicate keys](operator[].md#notes)). 2. Returns the array element at index `idx`. The template accepts every integer type except `#!cpp bool` and `#!cpp std::size_t` and forwards to the `size_type` overload, as for [`operator[]`](operator[].md); a negative @@ -62,7 +62,7 @@ Strong guarantee: there are no changes to the view or the document it refers to. - Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index in `ptr` is out of range. - Throws [`out_of_range.402`](../../home/exceptions.md#jsonexceptionout_of_range402) if a reference token is - `#!cpp "-"` at an array -- `at` never inserts an element, so `#!cpp "-"` is always invalid. + `#!cpp "-"` at an array — `at` never inserts an element, so `#!cpp "-"` is always invalid. - Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a reference token names an object member that does not exist. - Throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if `ptr` cannot be resolved @@ -76,7 +76,7 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics 1. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after another, in document order, stopping at the first match. Each comparison first checks the - key's length -- already known from the index, without reading the key bytes -- before comparing its content. + key's length — already known from the index, without reading the key bytes — before comparing its content. Objects with 128 or more members get a hash index of their keys while parsing, so that a lookup in them takes constant time on average. 2. Linear in `idx`: elements are skipped one at a time from the first one, since they are not a fixed size in the @@ -95,7 +95,7 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics the last value. Unlike [`operator[]`](operator[].md), which returns a [discarded](is_discarded.md) view for a missing key or an -out-of-range index, `at` always throws -- exactly as `BasicJsonType::at` does, and with the same messages, so +out-of-range index, `at` always throws — exactly as `BasicJsonType::at` does, and with the same messages, so existing error handling written against `BasicJsonType::at` keeps working unchanged when switched to a view. This also holds for overload 3: unlike [`operator[]`](operator[].md) with a JSON pointer, which returns a discarded view for a missing key or an out-of-range index, `at` throws for those too (`out_of_range.403`/`out_of_range.401`). @@ -105,7 +105,7 @@ for a missing key or an out-of-range index, `at` throws for those too (`out_of_r ??? example "Example: (1)/(2) access specified element with bounds checking" The example below reads required fields out of a service configuration with `at`, and shows that the exceptions - it throws -- for a wrong type and for a missing key -- carry the same messages + it throws — for a wrong type and for a missing key — carry the same messages [`BasicJsonType::at`](../basic_json/at.md) would produce for the same JSON text. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/begin.md b/docs/mkdocs/docs/api/basic_json_view/begin.md index ac1b0fda8..9c9974693 100644 --- a/docs/mkdocs/docs/api/basic_json_view/begin.md +++ b/docs/mkdocs/docs/api/basic_json_view/begin.md @@ -5,7 +5,7 @@ iterator begin() const noexcept; ``` Returns an iterator to the first element of an array, or the first member value of an object, in **document order** --- the order the values appear in the source text, not sorted by key. A primitive value iterates as a range of one +— the order the values appear in the source text, not sorted by key. A primitive value iterates as a range of one element (itself), and a `#!json null` value or a [discarded](is_discarded.md) view iterates as an empty range. ## Return value @@ -22,7 +22,7 @@ Constant. ## Notes -For an object, iteration visits **every** member, including all occurrences of a duplicate key -- unlike +For an object, iteration visits **every** member, including all occurrences of a duplicate key — unlike [`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md), and [`contains`](contains.md), which all resolve to the *first* member with a given key. See the [Notes on duplicate keys](operator[].md#notes) of `operator[]`. diff --git a/docs/mkdocs/docs/api/basic_json_view/cbegin.md b/docs/mkdocs/docs/api/basic_json_view/cbegin.md index 19d431dbd..bd6674230 100644 --- a/docs/mkdocs/docs/api/basic_json_view/cbegin.md +++ b/docs/mkdocs/docs/api/basic_json_view/cbegin.md @@ -25,7 +25,7 @@ Constant. ??? example The example below sums many measurements with `std::accumulate`, using `cbegin()`/[`cend()`](cend.md) as the - range -- the same way it would for any standard container -- without ever materializing the whole array into a + range — the same way it would for any standard container — without ever materializing the whole array into a `BasicJsonType` value. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/cend.md b/docs/mkdocs/docs/api/basic_json_view/cend.md index 8f41ce201..cd7def05c 100644 --- a/docs/mkdocs/docs/api/basic_json_view/cend.md +++ b/docs/mkdocs/docs/api/basic_json_view/cend.md @@ -25,7 +25,7 @@ Constant. ??? example The example below checks that every record of a batch is an object with `std::all_of`, using - [`cbegin()`](cbegin.md)/`cend()` as the range -- the same way it would for any standard container -- before + [`cbegin()`](cbegin.md)/`cend()` as the range — the same way it would for any standard container — before materializing any record of the batch. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/contains.md b/docs/mkdocs/docs/api/basic_json_view/contains.md index f7c87c808..dc1208125 100644 --- a/docs/mkdocs/docs/api/basic_json_view/contains.md +++ b/docs/mkdocs/docs/api/basic_json_view/contains.md @@ -34,11 +34,11 @@ No-throw guarantee: this function never throws exceptions. 1. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after another, in document order, stopping at the first match. Each comparison first checks the - key's length -- already known from the index, without reading the key bytes -- before comparing its content. + key's length — already known from the index, without reading the key bytes — before comparing its content. Objects with 128 or more members get a hash index of their keys while parsing, so that a lookup in them takes constant time on average. 2. Linear in the number of reference tokens of `ptr` and, for each token, in the number of members of the object at - that level or the index into the array -- as for [`operator[]`](operator[].md#complexity) and + that level or the index into the array — as for [`operator[]`](operator[].md#complexity) and [`at`](at.md#complexity) with a JSON pointer. ## Notes @@ -50,7 +50,7 @@ No-throw guarantee: this function never throws exceptions. `operator[]` and [Duplicate keys](../../features/json_view.md#duplicate-keys) for the reasons and for how to get the last value. -Overload 1 always returns `#!cpp false` when the value is not an object -- including a [discarded](is_discarded.md) +Overload 1 always returns `#!cpp false` when the value is not an object — including a [discarded](is_discarded.md) view. !!! info "Postconditions" diff --git a/docs/mkdocs/docs/api/basic_json_view/count.md b/docs/mkdocs/docs/api/basic_json_view/count.md index eba34b912..81d12915c 100644 --- a/docs/mkdocs/docs/api/basic_json_view/count.md +++ b/docs/mkdocs/docs/api/basic_json_view/count.md @@ -27,13 +27,13 @@ No-throw guarantee: this function never throws exceptions. Linear in the number of members: unlike the lookup functions, `count()` does not stop at the first match, because it has to count every member with the key. Members are compared one after another, in document order. Each comparison -first checks the key's length -- already known from the index, without reading the key bytes -- before comparing its +first checks the key's length — already known from the index, without reading the key bytes — before comparing its content. The hash index of the keys of objects with 128 or more members does not help here, since every member is visited. ## Notes -This method always returns `#!cpp 0` when the value is not an object -- including a [discarded](is_discarded.md) +This method always returns `#!cpp 0` when the value is not an object — including a [discarded](is_discarded.md) view. If the source text repeats a key, `count()` returns more than `#!cpp 1` for it, even though the diff --git a/docs/mkdocs/docs/api/basic_json_view/dump.md b/docs/mkdocs/docs/api/basic_json_view/dump.md index 7d829d422..a47ca6085 100644 --- a/docs/mkdocs/docs/api/basic_json_view/dump.md +++ b/docs/mkdocs/docs/api/basic_json_view/dump.md @@ -11,7 +11,7 @@ Serializes this value (and its subtree) directly from the flat index, without ev first. With the default `#!cpp numbers == number_format::shortest`, the result is the same string [`BasicJsonType::dump`](../basic_json/dump.md) would produce for the value [`BasicJsonType::parse()`](../basic_json/parse.md) builds from the same source text, called with the same `indent`, -`indent_char`, and `ensure_ascii` -- except that members of an object appear in document order rather than sorted by +`indent_char`, and `ensure_ascii` — except that members of an object appear in document order rather than sorted by key, and *every* occurrence of a repeated key is written rather than only the last one (see [Notes on duplicate keys](operator[].md#notes)). For a `json_view` (whose `BasicJsonType` is not ordered), this means `dump()` can print an object's members in a different order than [`materialize()`](materialize.md)`.dump()` of the @@ -58,19 +58,19 @@ Linear in the size of the output text. ## Notes The walk over the subtree is iterative, so the nesting depth it can write is limited by available memory only, not by -the call stack -- as for [`materialize()`](materialize.md). +the call stack — as for [`materialize()`](materialize.md). Strings are escaped by the same rules as [`BasicJsonType::dump`](../basic_json/dump.md). With `#!cpp numbers == number_format::shortest`, floats are written with the library's shortest round-trip conversion, exactly as [`BasicJsonType::dump`](../basic_json/dump.md) would (e.g. `#!cpp 1.5`, `#!cpp 100.0`, `#!cpp 1e+100`), and -integers are copied from the source text -- already canonical in JSON, so this matches their shortest form too -- +integers are copied from the source text — already canonical in JSON, so this matches their shortest form too — except that `#!cpp -0` is written as `#!cpp 0`, the way [`BasicJsonType::parse()`](../basic_json/parse.md) reads it. `#!cpp number_format::source` copies every number exactly as written in the source text instead, with no exception -for `#!cpp -0` -- `#!cpp 1.50`, `#!cpp 1E2`, `#!cpp -0.0`, `#!cpp -0`, or all digits of an integer literal with more +for `#!cpp -0` — `#!cpp 1.50`, `#!cpp 1E2`, `#!cpp -0.0`, `#!cpp -0`, or all digits of an integer literal with more digits than any number type holds (such a literal is itself classified as a float, see -[What is different](../../features/json_view.md#what-is-different)) -- something `BasicJsonType` cannot do, since +[What is different](../../features/json_view.md#what-is-different)) — something `BasicJsonType` cannot do, since parsing already reduces every number to its parsed value. ## Examples diff --git a/docs/mkdocs/docs/api/basic_json_view/empty.md b/docs/mkdocs/docs/api/basic_json_view/empty.md index 5c9cf73e5..82c1d10e3 100644 --- a/docs/mkdocs/docs/api/basic_json_view/empty.md +++ b/docs/mkdocs/docs/api/basic_json_view/empty.md @@ -31,7 +31,7 @@ Constant. ## Notes -As for [`BasicJsonType::empty()`](../basic_json/empty.md), this does not return whether a string value is empty -- it +As for [`BasicJsonType::empty()`](../basic_json/empty.md), this does not return whether a string value is empty — it is `#!cpp false` for any string, regardless of its length. ## Examples diff --git a/docs/mkdocs/docs/api/basic_json_view/end.md b/docs/mkdocs/docs/api/basic_json_view/end.md index f449608ec..adbf33137 100644 --- a/docs/mkdocs/docs/api/basic_json_view/end.md +++ b/docs/mkdocs/docs/api/basic_json_view/end.md @@ -5,7 +5,7 @@ iterator end() const noexcept; ``` Returns an iterator to one past the last element of an array, one past the last member value of an object, in -**document order** -- see [`begin()`](begin.md). A primitive value iterates as a range of one element (itself), and a +**document order** — see [`begin()`](begin.md). A primitive value iterates as a range of one element (itself), and a `#!json null` value or a [discarded](is_discarded.md) view iterates as an empty range (`#!cpp begin() == end()`). ## Return value diff --git a/docs/mkdocs/docs/api/basic_json_view/find.md b/docs/mkdocs/docs/api/basic_json_view/find.md index d61cfd661..b55741ca5 100644 --- a/docs/mkdocs/docs/api/basic_json_view/find.md +++ b/docs/mkdocs/docs/api/basic_json_view/find.md @@ -6,7 +6,7 @@ iterator find(const char* key) const; iterator find(const string_t& key) const; ``` -Finds a member with key `key` -- the first one, should the key occur more than once (see +Finds a member with key `key` — the first one, should the key occur more than once (see [Notes on duplicate keys](operator[].md#notes)). If the value is not an object, or no member has this key, [`end()`](end.md) is returned. @@ -27,7 +27,7 @@ No-throw guarantee: this function never throws exceptions. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after another, in document order, stopping at the first match. Each comparison first checks the key's length --- already known from the index, without reading the key bytes -- before comparing its content. +— already known from the index, without reading the key bytes — before comparing its content. Objects with 128 or more members get a hash index of their keys while parsing, so that a lookup in them takes constant time on average. @@ -41,7 +41,7 @@ constant time on average. the last value. Unlike [`BasicJsonType::find`](../basic_json/find.md), which always returns `#!cpp end()` for a non-object type, this -also does so for a [discarded](is_discarded.md) view -- there is no separate "invalid" iterator to return. +also does so for a [discarded](is_discarded.md) view — there is no separate "invalid" iterator to return. ## Examples diff --git a/docs/mkdocs/docs/api/basic_json_view/get.md b/docs/mkdocs/docs/api/basic_json_view/get.md index 765980882..596fc5274 100644 --- a/docs/mkdocs/docs/api/basic_json_view/get.md +++ b/docs/mkdocs/docs/api/basic_json_view/get.md @@ -7,19 +7,19 @@ T get() const; Converts the value to `T`. -For the types below, the conversion works directly on the flat index -- no `BasicJsonType` value is built for it: +For the types below, the conversion works directly on the flat index — no `BasicJsonType` value is built for it: - `#!cpp bool` - arithmetic types other than `#!cpp bool` (for a boolean, `#!cpp 0`/`#!cpp 1`, exactly as for [`BasicJsonType::get()`](../basic_json/get.md)) - `#!cpp std::nullptr_t` -- `#!cpp std::basic_string` (including `string_t`) -- a copy of the string -- [`string_view_t`](index.md#member-types) -- **no copy**: the returned view points into the document's +- `#!cpp std::basic_string` (including `string_t`) — a copy of the string +- [`string_view_t`](index.md#member-types) — **no copy**: the returned view points into the document's [`source()`](../basic_json_document/source.md) text, or, for a string that contains escape sequences, into the document's own buffer of decoded strings (see [`get_string()`](get_string.md)) -- `BasicJsonType` -- equivalent to [`materialize()`](materialize.md) -- `basic_json_view` -- returns `#!cpp *this` -- `#!cpp std::vector` -- from an array, element by element, each converted with `#!cpp get()`; `#!cpp +- `BasicJsonType` — equivalent to [`materialize()`](materialize.md) +- `basic_json_view` — returns `#!cpp *this` +- `#!cpp std::vector` — from an array, element by element, each converted with `#!cpp get()`; `#!cpp std::vector` keeps a view of every element instead of a value - `#!cpp std::map` and `#!cpp std::unordered_map`, if `K` is constructible from a `#!cpp (const char*, std::size_t)` pair -- from an object, member by member, each value converted with `#!cpp get()`; with a repeated @@ -27,8 +27,8 @@ For the types below, the conversion works directly on the flat index -- no `Basi [`materialize()`](materialize.md)) does; `#!cpp std::map` keeps views of the members instead of values -Every other `T` -- `#!cpp std::list`, `#!cpp std::pair`, `#!cpp std::array`, enumerations, user types with a -`from_json()`, ... -- is converted by `#!cpp materialize().get()`: the subtree is built into a real `BasicJsonType` +Every other `T` — `#!cpp std::list`, `#!cpp std::pair`, `#!cpp std::array`, enumerations, user types with a +`from_json()`, ... — is converted by `#!cpp materialize().get()`: the subtree is built into a real `BasicJsonType` value first (as [`BasicJsonType::parse()`](../basic_json/parse.md) would), and converted from there exactly as [`BasicJsonType::get()`](../basic_json/get.md) would convert it. @@ -49,13 +49,13 @@ Strong guarantee: there are no changes to the view or the document it refers to. - For the directly-converted types listed above (other than `BasicJsonType` and `basic_json_view`, which never throw): throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if the value's type does not - match `T` -- the same exception, with the same message, that [`BasicJsonType::get()`](../basic_json/get.md) + match `T` — the same exception, with the same message, that [`BasicJsonType::get()`](../basic_json/get.md) throws for the same JSON type and `T`. - For `#!cpp std::vector`: throws `type_error.302` if the value is not an array; otherwise, whatever converting an element to `U` throws. - For `#!cpp std::map`/`#!cpp std::unordered_map`: throws `type_error.302` if the value is not an object; otherwise, whatever converting a member to the mapped type throws. -- For every other `T`: whatever [`materialize().get()`](../basic_json/get.md) throws -- typically `type_error.302`, +- For every other `T`: whatever [`materialize().get()`](../basic_json/get.md) throws — typically `type_error.302`, or whatever a user-provided `from_json()` throws. None of the exceptions thrown directly by this function (the first three bullets above) carry a @@ -107,7 +107,7 @@ document. The example below reads typed fields straight into C++ variables, collects a view of every array element with `#!cpp get>()` instead of a value, and converts a nested object into a user type - through its `from_json()` -- which runs on a `BasicJsonType` value `materialize()` builds for just that one + through its `from_json()` — which runs on a `BasicJsonType` value `materialize()` builds for just that one member. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/get_string.md b/docs/mkdocs/docs/api/basic_json_view/get_string.md index c68ac6442..7539c540d 100644 --- a/docs/mkdocs/docs/api/basic_json_view/get_string.md +++ b/docs/mkdocs/docs/api/basic_json_view/get_string.md @@ -41,8 +41,8 @@ counterpart, except that it returns a view instead of a reference to a value tha document, the returned [`string_view_t`](index.md#member-types) is valid as long as the caller's buffer; for an owned one, as long as the document. -The returned [`string_view_t`](index.md#member-types) is valid exactly as long as the view that produced it -- see the -[validity rules](index.md) of `basic_json_view` -- and, for a string with no escapes, for as long as the document's +The returned [`string_view_t`](index.md#member-types) is valid exactly as long as the view that produced it — see the +[validity rules](index.md) of `basic_json_view` — and, for a string with no escapes, for as long as the document's source text, which for a borrowed document must remain valid **and unmodified** for as long as the document exists, since floating-point values and unescaped strings are read from the source lazily. @@ -52,8 +52,8 @@ since floating-point values and unescaped strings are read from the source lazil The example below pulls one field out of a JSON text that stands in for a large API response, and shows that no `#!cpp std::string` was allocated for it: the returned view still points inside the original buffer. A field that - contains an escape sequence cannot point into the original text -- it was decoded once into the document's own - buffer instead -- but still avoids a per-field allocation. + contains an escape sequence cannot point into the original text — it was decoded once into the document's own + buffer instead — but still avoids a per-field allocation. ```cpp --8<-- "examples/basic_json_view__get_string.cpp" diff --git a/docs/mkdocs/docs/api/basic_json_view/get_to.md b/docs/mkdocs/docs/api/basic_json_view/get_to.md index 1e1ad9d71..41d204190 100644 --- a/docs/mkdocs/docs/api/basic_json_view/get_to.md +++ b/docs/mkdocs/docs/api/basic_json_view/get_to.md @@ -7,9 +7,9 @@ T& get_to(T& v) const; Converts the value to `T` and stores it in `v`, in one of two ways: -- For the types that [`get()`](get.md) converts directly -- arithmetic types, `#!cpp bool`, +- For the types that [`get()`](get.md) converts directly — arithmetic types, `#!cpp bool`, `#!cpp std::nullptr_t`, [`string_view_t`](index.md#member-types), `#!cpp std::basic_string`, `BasicJsonType`, - `basic_json_view`, `#!cpp std::vector`, and `#!cpp std::map`/`#!cpp std::unordered_map` with string keys -- `v` is + `basic_json_view`, `#!cpp std::vector`, and `#!cpp std::map`/`#!cpp std::unordered_map` with string keys — `v` is assigned: `#!cpp v = get()`. - For every other type, the subtree is built into a `BasicJsonType` value and `#!cpp materialize().get_to(v)` is called, i.e. `from_json()` is invoked with the existing `v`, exactly as diff --git a/docs/mkdocs/docs/api/basic_json_view/index.md b/docs/mkdocs/docs/api/basic_json_view/index.md index 84c09afb4..479978f85 100644 --- a/docs/mkdocs/docs/api/basic_json_view/index.md +++ b/docs/mkdocs/docs/api/basic_json_view/index.md @@ -36,11 +36,11 @@ Moving the document itself does not invalidate its views: the index is heap-allo [`json_pointer`](../json_pointer/index.md). Unlike `basic_json`, there are no implicit conversion operators (no `#!cpp operator ValueType()`), and no `#!cpp get_ptr()` or `#!cpp get_ref()`; see [`get`](get.md). -`basic_json_view` itself is always read-only -- it never has a `set` or `push_back` of its own. A view of an +`basic_json_view` itself is always read-only — it never has a `set` or `push_back` of its own. A view of an **editable** document (`#!cpp Editable == true`) sees every edit made through [`basic_json_document::set`](../basic_json_document/set.md) and [`basic_json_document::push_back`](../basic_json_document/push_back.md): once a value is changed, every view that -still refers to it -- including ones taken before the change -- reads the new value. See +still refers to it — including ones taken before the change — reads the new value. See [Edits](../basic_json_document/index.md#edits). ## Template parameters diff --git a/docs/mkdocs/docs/api/basic_json_view/is_discarded.md b/docs/mkdocs/docs/api/basic_json_view/is_discarded.md index 049019aff..e6751c12c 100644 --- a/docs/mkdocs/docs/api/basic_json_view/is_discarded.md +++ b/docs/mkdocs/docs/api/basic_json_view/is_discarded.md @@ -6,7 +6,7 @@ bool is_discarded() const noexcept; Returns whether this view is invalid, i.e. does not refer to a value. This is the case for a default-constructed view (see [(constructor)](basic_json_view.md)), and for [`root()`](../basic_json_document/root.md) of a document -that is itself [discarded](../basic_json_document/is_discarded.md) -- in particular, the root of a failed +that is itself [discarded](../basic_json_document/is_discarded.md) — in particular, the root of a failed [`parse()`](../basic_json_document/parse.md) with `allow_exceptions` set to `#!cpp false`. A discarded view is also what [`operator[]`](operator[].md) returns for a missing key, an index out of range, or a diff --git a/docs/mkdocs/docs/api/basic_json_view/items.md b/docs/mkdocs/docs/api/basic_json_view/items.md index 36de65272..9f1efffef 100644 --- a/docs/mkdocs/docs/api/basic_json_view/items.md +++ b/docs/mkdocs/docs/api/basic_json_view/items.md @@ -4,7 +4,7 @@ /* unspecified */ items() const noexcept; ``` -Returns a range of items -- (key, value) pairs -- for use in range-based for loops. An item's `#!cpp key()` is a +Returns a range of items — (key, value) pairs — for use in range-based for loops. An item's `#!cpp key()` is a `#!cpp string_view_t` (for an array element, its index converted to a string, as for [`BasicJsonType::items()`](../basic_json/items.md)), and its `#!cpp value()` is a `basic_json_view` of the element. @@ -47,7 +47,7 @@ Constant. ## Notes As for [`begin()`](begin.md)/[`end()`](end.md), `items()` visits **every** member of an object, including all -occurrences of a duplicate key -- unlike [`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md), +occurrences of a duplicate key — unlike [`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md), and [`contains`](contains.md), which resolve to the *first* member with a given key. See the [Notes on duplicate keys](operator[].md#notes) of `operator[]`. @@ -63,8 +63,8 @@ and [`contains`](contains.md), which resolve to the *first* member with a given The example below shows a settings object whose source text records every update to a key as a duplicate member, in the order they happened. `items()` walks all of them, so the update history is visible, while - [`operator[]`](operator[].md) only ever sees the *first* one and [`materialize()`](materialize.md) -- like - [`BasicJsonType::parse()`](../basic_json/parse.md) -- keeps only the *last*. + [`operator[]`](operator[].md) only ever sees the *first* one and [`materialize()`](materialize.md) — like + [`BasicJsonType::parse()`](../basic_json/parse.md) — keeps only the *last*. ```cpp --8<-- "examples/basic_json_view__items.cpp" diff --git a/docs/mkdocs/docs/api/basic_json_view/materialize.md b/docs/mkdocs/docs/api/basic_json_view/materialize.md index 72dcdcd97..f29a25cda 100644 --- a/docs/mkdocs/docs/api/basic_json_view/materialize.md +++ b/docs/mkdocs/docs/api/basic_json_view/materialize.md @@ -28,7 +28,7 @@ Linear in the size of the subtree. ## Notes `materialize()` replays the subtree through the same SAX builder [`BasicJsonType::parse()`](../basic_json/parse.md) -uses, so the result matches it exactly -- including, for an object, that a repeated key keeps only its +uses, so the result matches it exactly — including, for an object, that a repeated key keeps only its last value. The replay is iterative, so it is not limited by the call stack the way a naive recursive conversion would be; the JSON nesting depth is limited only by available memory, as for `BasicJsonType::parse()` itself. @@ -43,7 +43,7 @@ never caches the result. ??? example - The example below skips messages that are not useful -- a discarded value, or an empty array -- using only + The example below skips messages that are not useful — a discarded value, or an empty array — using only [`is_array()`](is_array.md) and [`empty()`](empty.md), and calls `materialize()` only for the messages that are actually used, so no `BasicJsonType` value (and none of its per-element allocations) is ever built for the skipped ones. diff --git a/docs/mkdocs/docs/api/basic_json_view/number_format.md b/docs/mkdocs/docs/api/basic_json_view/number_format.md index 711e74544..01c06193e 100644 --- a/docs/mkdocs/docs/api/basic_json_view/number_format.md +++ b/docs/mkdocs/docs/api/basic_json_view/number_format.md @@ -10,14 +10,14 @@ enum class number_format { This enumeration is used in [`dump`](dump.md) to choose how numbers are written. Two values are differentiated: shortest -: integers are copied from the source text -- already canonical in JSON -- except that `#!cpp -0` becomes +: integers are copied from the source text — already canonical in JSON — except that `#!cpp -0` becomes `#!cpp 0`, the way [`BasicJsonType::parse()`](../basic_json/parse.md) reads it; floats are written with the library's shortest round-trip conversion, exactly as [`BasicJsonType::dump()`](../basic_json/dump.md) would (e.g. `#!cpp 1.5`, `#!cpp 100.0`, `#!cpp 1e+100`) source -: every number is copied exactly as it appears in the source text -- `#!cpp 1.50`, `#!cpp 1E2`, `#!cpp -0`, all - digits of an integer literal with more digits than any number type holds -- something `BasicJsonType` cannot do, +: every number is copied exactly as it appears in the source text — `#!cpp 1.50`, `#!cpp 1E2`, `#!cpp -0`, all + digits of an integer literal with more digits than any number type holds — something `BasicJsonType` cannot do, since parsing already reduces every number to its parsed value ## Examples diff --git a/docs/mkdocs/docs/api/basic_json_view/number_token.md b/docs/mkdocs/docs/api/basic_json_view/number_token.md index 1236c35a7..97d7a2ed2 100644 --- a/docs/mkdocs/docs/api/basic_json_view/number_token.md +++ b/docs/mkdocs/docs/api/basic_json_view/number_token.md @@ -9,7 +9,7 @@ Returns the number exactly as it appears in the source text, without parsing or ## Return value The number's token text, as a [`string_view_t`](index.md#member-types) into the document's -[`source()`](../basic_json_document/source.md) text -- for example `#!cpp "1.50"`, `#!cpp "1E2"`, `#!cpp "-0"`, or an +[`source()`](../basic_json_document/source.md) text — for example `#!cpp "1.50"`, `#!cpp "1E2"`, `#!cpp "-0"`, or an integer literal with more digits than any number type holds (such as a 30-digit integer, which [`get()`](get.md) and [`materialize()`](materialize.md) can only represent approximately, as a `number_float_t`). @@ -35,12 +35,12 @@ Constant. `BasicJsonType` has no counterpart to this function: once a number is parsed into `number_integer_t`, `number_unsigned_t`, or `number_float_t`, its original textual form (leading zeros aside, which are already rejected by the grammar; trailing zeros in the fraction; the case and sign of the exponent; ...) is gone. `number_token()` is -useful precisely where that form must survive -- a price or an identifier that must be reproduced exactly, or a +useful precisely where that form must survive — a price or an identifier that must be reproduced exactly, or a number too large for any of `BasicJsonType`'s number types to hold without loss. The returned [`string_view_t`](index.md#member-types) always points into the document's -[`source()`](../basic_json_document/source.md) text -- numbers are never decoded into the document's separate string -buffer -- and is valid exactly as long as that text is, see the [validity rules](index.md) of `basic_json_view`. +[`source()`](../basic_json_document/source.md) text — numbers are never decoded into the document's separate string +buffer — and is valid exactly as long as that text is, see the [validity rules](index.md) of `basic_json_view`. ## Examples @@ -48,7 +48,7 @@ buffer -- and is valid exactly as long as that text is, see the [validity rules] The example below keeps a price and an order ID exactly as they were written in an incoming order, where converting them with [`get()`](get.md) would lose information: the price picks up floating-point rounding, and - the order ID -- more digits than a 64-bit integer holds -- can only be approximated as a `#!cpp double` once + the order ID — more digits than a 64-bit integer holds — can only be approximated as a `#!cpp double` once `#!cpp materialize()`d. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/operator[].md b/docs/mkdocs/docs/api/basic_json_view/operator[].md index 74d1e356b..9c09a807b 100644 --- a/docs/mkdocs/docs/api/basic_json_view/operator[].md +++ b/docs/mkdocs/docs/api/basic_json_view/operator[].md @@ -15,8 +15,8 @@ basic_json_view operator[](IntegerType idx) const; basic_json_view operator[](const json_pointer& ptr) const; ``` -1. Returns the value of the object member with key `key` -- the first one, should the key occur more than once (see - the [Notes](#notes) below) -- or a [discarded](is_discarded.md) view if there is no such member. +1. Returns the value of the object member with key `key` — the first one, should the key occur more than once (see + the [Notes](#notes) below) — or a [discarded](is_discarded.md) view if there is no such member. 2. Returns the array element at index `idx`, or a [discarded](is_discarded.md) view if `idx` is out of range. The template accepts every integer type except `#!cpp bool` and `#!cpp std::size_t` (`#!cpp int`, `#!cpp unsigned`, `#!cpp long`, `#!cpp std::int64_t`, ...) and forwards to the `size_type` overload, so that an integer argument is @@ -55,11 +55,11 @@ Strong guarantee: there are no changes to the view or the document it refers to. ## Exceptions 1. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an object and - not [discarded](is_discarded.md) -- + not [discarded](is_discarded.md) — the same exception, with the same message, that the **const** overload of [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) throws for a string argument on a non-object value. 2. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an array and - not [discarded](is_discarded.md) -- + not [discarded](is_discarded.md) — the same exception, with the same message, that the **const** overload of [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) throws for a numeric argument on a non-array value. 3. Throws the same exceptions, with the same messages, that the **const** overload of @@ -81,7 +81,7 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics 1. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after another, in document order, stopping at the first match. Each comparison first checks the - key's length -- already known from the index, without reading the key bytes -- before comparing its content, so a + key's length — already known from the index, without reading the key bytes — before comparing its content, so a key of a different length than `key` is rejected without touching the source text. Objects with 128 or more members get a hash index of their keys while parsing, so that a lookup in them takes constant time on average. @@ -97,7 +97,7 @@ Unlike `BasicJsonType::operator[]`, which is undefined behavior (guarded by a [runtime assertion](../../features/assertions.md)) for a missing key on a **const** value, this operator returns a safe, testable result for a missing key or an index out of range: a [discarded](is_discarded.md) view, which is tested with [`is_discarded`](is_discarded.md). -There is also no non-const overload that inserts a missing key or extends an array -- a view never modifies the +There is also no non-const overload that inserts a missing key or extends an array — a view never modifies the document. !!! info "Chained access" @@ -126,8 +126,8 @@ document. Overload 3 walks `ptr` one reference token at a time, starting at this value, the same way [`at`](at.md) and [`contains`](contains.md) do. It only ever returns a discarded view where the **const** overload of - `BasicJsonType::operator[]` would be undefined behavior for the same pointer -- a missing object member or an - out-of-range array index -- and still throws for every other way `ptr` can fail to resolve. See + `BasicJsonType::operator[]` would be undefined behavior for the same pointer — a missing object member or an + out-of-range array index — and still throws for every other way `ptr` can fail to resolve. See [`at`](at.md#exceptions) for the checked version, which throws in every case instead, and [`contains`](contains.md) for a version that never throws. @@ -137,7 +137,7 @@ document. The example below reads a couple of fields out of a batch of user records without ever materializing a full `BasicJsonType` value for the batch. `operator[]` is used both to look up an optional object member and to index - into an array -- in both cases, a missing value comes back as a discarded view that can be tested with a plain + into an array — in both cases, a missing value comes back as a discarded view that can be tested with a plain `#!cpp if`, instead of relying on undefined behavior. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/operator_eq.md b/docs/mkdocs/docs/api/basic_json_view/operator_eq.md index 7cfe8d443..26ff303f6 100644 --- a/docs/mkdocs/docs/api/basic_json_view/operator_eq.md +++ b/docs/mkdocs/docs/api/basic_json_view/operator_eq.md @@ -17,7 +17,7 @@ bool operator==(const BasicJsonType& lhs, const basic_json_view& rhs); Neither overload builds a `BasicJsonType` value for a view to do the comparison (see [Notes](#notes) below). Numbers compare by value across their types (`#!cpp 1 == 1.0`), and an object compares by its members, with duplicate keys -resolved exactly as `parse()` resolves them -- the last value, at the position of the first occurrence of the key. +resolved exactly as `parse()` resolves them — the last value, at the position of the first occurrence of the key. This is not what [`operator[]`](operator[].md) and the other lookups return for a duplicate key: they find the *first* member (see [Duplicate keys](../../features/json_view.md#duplicate-keys)). @@ -55,7 +55,7 @@ compared. Two arrays of different [`size()`](size.md) are rejected without visit ## Notes Only a single number, boolean, or `#!cpp null` value is ever materialized into a `BasicJsonType`, to reuse its -`operator==` -- for numbers, so that values written differently in the source text but equal in value (e.g. an +`operator==` — for numbers, so that values written differently in the source text but equal in value (e.g. an integer and a floating-point literal) still compare equal, following the same rules `BasicJsonType` does for special values such as `#!cpp NaN`. Constructing one of these scalars never allocates. Strings are compared directly, without allocating, either from the source text on both sides or, for overload 2, against `BasicJsonType`'s own string. @@ -85,7 +85,7 @@ the way to get a `BasicJsonType` value that supports it. ??? example The example below checks whether a newly received configuration differs from the previous one, and whether a - received document matches what a test expects -- directly on views, without ever materializing a `BasicJsonType` + received document matches what a test expects — directly on views, without ever materializing a `BasicJsonType` value for either side. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/operator_ltlt.md b/docs/mkdocs/docs/api/basic_json_view/operator_ltlt.md index 47516525b..3ee5961fb 100644 --- a/docs/mkdocs/docs/api/basic_json_view/operator_ltlt.md +++ b/docs/mkdocs/docs/api/basic_json_view/operator_ltlt.md @@ -6,7 +6,7 @@ std::ostream& operator<<(std::ostream& o, const basic_json_view& v); Not available when [`JSON_NO_IO`](../macros/json_no_io.md) is defined. -Serializes the given view `v` to the output stream `o`, using [`dump`](dump.md) -- exactly as +Serializes the given view `v` to the output stream `o`, using [`dump`](dump.md) — exactly as `#!cpp operator<<(std::ostream&, const basic_json&)` does for a `basic_json` value. - The indentation of the output can be controlled with the member variable `width` of the output stream `o`. For @@ -38,7 +38,7 @@ the stream `o` May throw `#!cpp std::bad_alloc`, propagated from [`dump`](dump.md#exceptions). Unlike `#!cpp operator<<(std::ostream&, const basic_json&)`, there is no UTF-8 decoding step that could throw -[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316), and no `error_handler` to choose between -- +[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316), and no `error_handler` to choose between — see the [Exceptions](dump.md#exceptions) of `dump`. ## Complexity @@ -49,8 +49,8 @@ Linear, as [`dump`](dump.md#complexity). ??? example - The example below writes one record out of a larger batch straight to a log stream -- compact for a one-line - entry, and pretty-printed with `std::setw`/`std::setfill` for a readable dump -- without ever building a + The example below writes one record out of a larger batch straight to a log stream — compact for a one-line + entry, and pretty-printed with `std::setw`/`std::setfill` for a readable dump — without ever building a `BasicJsonType` value for the record, or for the rest of the batch. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/operator_ne.md b/docs/mkdocs/docs/api/basic_json_view/operator_ne.md index 5d1950ac6..d4bb32f34 100644 --- a/docs/mkdocs/docs/api/basic_json_view/operator_ne.md +++ b/docs/mkdocs/docs/api/basic_json_view/operator_ne.md @@ -15,7 +15,7 @@ bool operator!=(const BasicJsonType& lhs, const basic_json_view& rhs); Since `operator!=` is defined as the negation of [`operator==`](operator_eq.md), it follows the same rules for special cases: for instance, since a [discarded](is_discarded.md) view is never equal to anything by default (see -[operator=='s Notes](operator_eq.md#notes)), it is never *unequal* to anything either -- `#!cpp discarded != discarded` +[operator=='s Notes](operator_eq.md#notes)), it is never *unequal* to anything either — `#!cpp discarded != discarded` is also `#!cpp false`, exactly as for a discarded `BasicJsonType` value. ## Parameters @@ -46,7 +46,7 @@ Linear, as [`operator==`](operator_eq.md#complexity). ## Notes -See the [Notes](operator_eq.md#notes) of `operator==` -- in particular for how an object's members are compared +See the [Notes](operator_eq.md#notes) of `operator==` — in particular for how an object's members are compared (order matters for [`ordered_json_view`](../ordered_json_view.md) but not for [`json_view`](../json_view.md)) and for how discarded views compare. @@ -58,7 +58,7 @@ the way to get a `BasicJsonType` value that supports it. ??? example The example below asserts, as a test would, that a received document differs from an unwanted value, and shows - that -- as for [`json`](../json.md)/[`ordered_json`](../ordered_json.md) -- reordering an object's members is + that — as for [`json`](../json.md)/[`ordered_json`](../ordered_json.md) — reordering an object's members is detected as a difference for an `ordered_json_view` but not for a `json_view`. ```cpp diff --git a/docs/mkdocs/docs/api/basic_json_view/size.md b/docs/mkdocs/docs/api/basic_json_view/size.md index 1c8c4f645..98473fccd 100644 --- a/docs/mkdocs/docs/api/basic_json_view/size.md +++ b/docs/mkdocs/docs/api/basic_json_view/size.md @@ -30,10 +30,10 @@ Constant: for an object or array, the element count is stored in the index, not ## Notes -As for [`BasicJsonType::size()`](../basic_json/size.md), this does not return the length of a string value -- it is +As for [`BasicJsonType::size()`](../basic_json/size.md), this does not return the length of a string value — it is `1` for a string, regardless of its length. -If the source text has an object with a duplicate key, every occurrence counts towards its `size()` -- unlike +If the source text has an object with a duplicate key, every occurrence counts towards its `size()` — unlike [`materialize()`](materialize.md) (and [`BasicJsonType::parse()`](../basic_json/parse.md)), which keeps only the last value for a repeated key. This means `#!cpp v.size()` can be larger than `#!cpp v.materialize().size()`. See the [Notes on duplicate keys](operator[].md#notes) of `operator[]` for why lookups and iteration disagree on how many diff --git a/docs/mkdocs/docs/api/basic_json_view/source_offset.md b/docs/mkdocs/docs/api/basic_json_view/source_offset.md index b9c6fb1eb..fb24caff3 100644 --- a/docs/mkdocs/docs/api/basic_json_view/source_offset.md +++ b/docs/mkdocs/docs/api/basic_json_view/source_offset.md @@ -13,7 +13,7 @@ materializing anything. byte offset of the first byte of the value's token (for a string: the first byte after the opening quote) in [`source()`](../basic_json_document/source.md). - `#!cpp static_cast(-1)` for a [discarded](is_discarded.md) view, and for a string that contains - escapes -- such a string was decoded once into the document's own buffer, so there is no single byte range in + escapes — such a string was decoded once into the document's own buffer, so there is no single byte range in `source()` left to point at. ## Exception safety diff --git a/docs/mkdocs/docs/api/basic_json_view/type.md b/docs/mkdocs/docs/api/basic_json_view/type.md index db875a1ce..b8aba36d8 100644 --- a/docs/mkdocs/docs/api/basic_json_view/type.md +++ b/docs/mkdocs/docs/api/basic_json_view/type.md @@ -5,7 +5,7 @@ value_t type() const noexcept; ``` Returns the type of the value this view refers to, as a value from the [`value_t`](../basic_json/value_t.md) -enumeration -- the same enumeration [`BasicJsonType::type()`](../basic_json/type.md) uses. +enumeration — the same enumeration [`BasicJsonType::type()`](../basic_json/type.md) uses. ## Return value diff --git a/docs/mkdocs/docs/api/basic_json_view/type_name.md b/docs/mkdocs/docs/api/basic_json_view/type_name.md index 44644c6f5..da4d78c03 100644 --- a/docs/mkdocs/docs/api/basic_json_view/type_name.md +++ b/docs/mkdocs/docs/api/basic_json_view/type_name.md @@ -4,7 +4,7 @@ const char* type_name() const noexcept; ``` -Returns the type name as string to be used in error messages -- usually to indicate that a function was called on a +Returns the type name as string to be used in error messages — usually to indicate that a function was called on a wrong JSON type. Identical to [`BasicJsonType::type_name()`](../basic_json/type_name.md), including the extra `#!cpp "discarded"` return value for a [discarded](is_discarded.md) view (`BasicJsonType::type_name()` produces the same string for a discarded `BasicJsonType` value). @@ -39,7 +39,7 @@ Constant. ??? example - The example below reports why some parsed messages were rejected, using only `type_name()` -- no + The example below reports why some parsed messages were rejected, using only `type_name()` — no `BasicJsonType` value is ever built for the ones that are wrong, and the message text matches what [`BasicJsonType::type_name()`](../basic_json/type_name.md) would produce for the same value. diff --git a/docs/mkdocs/docs/api/basic_json_view/value.md b/docs/mkdocs/docs/api/basic_json_view/value.md index cc4db8060..7159325b2 100644 --- a/docs/mkdocs/docs/api/basic_json_view/value.md +++ b/docs/mkdocs/docs/api/basic_json_view/value.md @@ -12,8 +12,8 @@ T value(const json_pointer& ptr, const T& default_value) const; string_t value(const json_pointer& ptr, const char* default_value) const; ``` -1. Returns the value of the object member with key `key` -- the first one, should the key occur more than once (see - [Notes on duplicate keys](operator[].md#notes)) -- converted to `T`, or `default_value` if there is no such member. +1. Returns the value of the object member with key `key` — the first one, should the key occur more than once (see + [Notes on duplicate keys](operator[].md#notes)) — converted to `T`, or `default_value` if there is no such member. 2. Returns the value a JSON pointer `ptr` refers to, starting at this value, converted to `T`, or `default_value` if `ptr` cannot be resolved. @@ -48,16 +48,16 @@ Strong guarantee: there are no changes to the view or the document it refers to. ## Exceptions -1. Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the value is not an object -- +1. Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the value is not an object — the same exception, with the same message, that [`BasicJsonType::value`](../basic_json/value.md) throws for the same call. If a member with key `key` is found, throws whatever converting it to `T` throws (typically [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302), with the same message [`BasicJsonType::value`](../basic_json/value.md) throws for the same mismatch); a missing member never throws. -2. Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if this value -- not the value `ptr` - resolves to -- is neither an object nor an array. Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) +2. Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if this value — not the value `ptr` + resolves to — is neither an object nor an array. Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) or [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if `ptr` contains a malformed array index. If `ptr` resolves to a value, throws whatever converting it to `T` throws. Every other way `ptr` can fail to - resolve -- a missing key, an out-of-range or "`-`" array index, an unresolvable token on a primitive -- yields + resolve — a missing key, an out-of-range or "`-`" array index, an unresolvable token on a primitive — yields `default_value` instead of throwing, exactly as [`BasicJsonType::value`](../basic_json/value.md) catches `out_of_range` and returns `default_value`. @@ -73,7 +73,7 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics Objects with 128 or more members get a hash index of their keys while parsing, so that a lookup in them takes constant time on average. 2. Linear in the number of reference tokens of `ptr` and, for each token, in the number of members of the object at - that level or the index into the array -- as for the [`operator[]`](operator[].md#complexity) and + that level or the index into the array — as for the [`operator[]`](operator[].md#complexity) and [`at`](at.md#complexity) overloads that take a JSON pointer. Plus the complexity of converting the resolved value to `T`. @@ -89,7 +89,7 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics !!! info "Differences to `at` and `operator[]`" Unlike [`at`](at.md), this function does not throw if `key`/`ptr` resolves to no value. Unlike - [`operator[]`](operator[].md), it never returns a [discarded](is_discarded.md) view -- it always returns a `T` -- + [`operator[]`](operator[].md), it never returns a [discarded](is_discarded.md) view — it always returns a `T` — and it is available on any view, since it never needs to insert a missing element the way the non-const `BasicJsonType::operator[]` would. diff --git a/docs/mkdocs/docs/api/byte_container_with_subtype/operator_eq.md b/docs/mkdocs/docs/api/byte_container_with_subtype/operator_eq.md index 6219cd0b7..085f80a94 100644 --- a/docs/mkdocs/docs/api/byte_container_with_subtype/operator_eq.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/operator_eq.md @@ -5,7 +5,7 @@ bool operator==(const byte_container_with_subtype& rhs) const; ``` Compares two byte containers for equality by comparing (1) the underlying binary data (the `BinaryType` base, compared -with `BinaryType`'s own `operator==`) and (2) the subtype information -- both containers must either have no subtype, +with `BinaryType`'s own `operator==`) and (2) the subtype information — both containers must either have no subtype, or have a subtype and the same subtype value. ## Parameters diff --git a/docs/mkdocs/docs/api/json_editable_document.md b/docs/mkdocs/docs/api/json_editable_document.md index b17c548af..879a37568 100644 --- a/docs/mkdocs/docs/api/json_editable_document.md +++ b/docs/mkdocs/docs/api/json_editable_document.md @@ -9,14 +9,14 @@ using json_editable_document = basic_json_document; This type is an **editable** [`basic_json_document`](basic_json_document/index.md) of the default [`json`](json.md) specialization: in addition to everything [`json_document`](json_document.md) offers, [`set`](basic_json_document/set.md) and [`push_back`](basic_json_document/push_back.md) change values after -parsing, without ever rewriting the source text -- see [Edits](basic_json_document/index.md#edits) and +parsing, without ever rewriting the source text — see [Edits](basic_json_document/index.md#edits) and [Editing a document](../features/json_view.md#editing-a-document). ## Examples ??? example - The example below patches two fields of a small configuration document -- changing one and adding another -- + The example below patches two fields of a small configuration document — changing one and adding another — and dumps it back out with the member order and the spelling of the untouched number preserved, something a plain [`json`](json.md) value cannot do. diff --git a/docs/mkdocs/docs/api/json_editable_view.md b/docs/mkdocs/docs/api/json_editable_view.md index fc347e3bc..cf236ccc1 100644 --- a/docs/mkdocs/docs/api/json_editable_view.md +++ b/docs/mkdocs/docs/api/json_editable_view.md @@ -8,7 +8,7 @@ using json_editable_view = basic_json_view; This type is a [`basic_json_view`](basic_json_view/index.md) of a value of a [`json_editable_document`](json_editable_document.md). It offers the same read-only interface as -[`json_view`](json_view.md); what is different is what it can be a view *of* -- a value that +[`json_view`](json_view.md); what is different is what it can be a view *of* — a value that [`set`](basic_json_document/set.md) and [`push_back`](basic_json_document/push_back.md) can change, with every view still referring to it seeing the change, see [Edits](basic_json_document/index.md#edits). @@ -17,7 +17,7 @@ still referring to it seeing the change, see [Edits](basic_json_document/index.m ??? example The example below is the same as [`json_editable_document`'s](json_editable_document.md): every view read back - out of the document -- `#!cpp doc.root()` and the views nested under it -- sees the edits made through `set`. + out of the document — `#!cpp doc.root()` and the views nested under it — sees the edits made through `set`. ```cpp --8<-- "examples/json_editable_document.cpp" diff --git a/docs/mkdocs/docs/api/macros/json_has_range_view_conversion.md b/docs/mkdocs/docs/api/macros/json_has_range_view_conversion.md index 5aa3059dc..4558916aa 100644 --- a/docs/mkdocs/docs/api/macros/json_has_range_view_conversion.md +++ b/docs/mkdocs/docs/api/macros/json_has_range_view_conversion.md @@ -17,7 +17,7 @@ When the macro is not defined, the library will define it to its default value. !!! info "Known compiler/stdlib exclusions" - - **MinGW** -- disabled, because its `std::ranges` support is incomplete ([issue #4916](https://github.com/nlohmann/json/issues/4916)). + - **MinGW** — disabled, because its `std::ranges` support is incomplete ([issue #4916](https://github.com/nlohmann/json/issues/4916)). - All toolchains for which [`JSON_HAS_RANGES`](json_has_ranges.md#default-definition) is disabled. ## Examples diff --git a/docs/mkdocs/docs/api/macros/json_use_simdutf.md b/docs/mkdocs/docs/api/macros/json_use_simdutf.md index 86edf5b8d..b6cf73ec8 100644 --- a/docs/mkdocs/docs/api/macros/json_use_simdutf.md +++ b/docs/mkdocs/docs/api/macros/json_use_simdutf.md @@ -24,7 +24,7 @@ simdutf library. When it is not defined, no simdutf header is included and there simdutf requires C++17 and its header rejects older standards with an `#!cpp #error`. The backend is therefore only compiled in from C++17 on. In C++11 and C++14 the macro has no effect and the scalar validator is used, which - accepts and rejects exactly the same input -- only throughput differs. Setting the macro project-wide is therefore + accepts and rejects exactly the same input — only throughput differs. Setting the macro project-wide is therefore safe even when some translation units are built with an older standard. !!! warning "Define consistently" diff --git a/docs/mkdocs/docs/api/operator_gtgt.md b/docs/mkdocs/docs/api/operator_gtgt.md index 9884e50c5..1263eee20 100644 --- a/docs/mkdocs/docs/api/operator_gtgt.md +++ b/docs/mkdocs/docs/api/operator_gtgt.md @@ -81,7 +81,7 @@ input >> j2; // parses the next value needed. This is tracked in [#5340](https://github.com/nlohmann/json/issues/5340). Note that reading concatenated values does **not** work for [JSON Lines](../features/parsing/json_lines.md) -(newline-delimited JSON) input -- see that page for why and for the recommended alternative. +(newline-delimited JSON) input — see that page for why and for the recommended alternative. By default, a `'\0'` (NUL) byte encountered while reading a value is treated as end of input, rather than as an ordinary (and, outside of a string, invalid) byte; see the [FAQ entry](../home/faq.md#nul-bytes-in-the-input) for diff --git a/docs/mkdocs/docs/api/ordered_json_editable_document.md b/docs/mkdocs/docs/api/ordered_json_editable_document.md index 8a614b0fd..10354795c 100644 --- a/docs/mkdocs/docs/api/ordered_json_editable_document.md +++ b/docs/mkdocs/docs/api/ordered_json_editable_document.md @@ -10,8 +10,8 @@ This type is an **editable** [`basic_json_document`](basic_json_document/index.m [`ordered_json`](ordered_json.md) specialization: [`set`](basic_json_document/set.md) and [`push_back`](basic_json_document/push_back.md) change values after parsing, as for [`json_editable_document`](json_editable_document.md), and -[`materialize()`](basic_json_view/materialize.md) preserves the document order of object members -- including -members [`set`](basic_json_document/set.md) added -- instead of sorting them like +[`materialize()`](basic_json_view/materialize.md) preserves the document order of object members — including +members [`set`](basic_json_document/set.md) added — instead of sorting them like [`json_editable_document`](json_editable_document.md) does. ## Examples diff --git a/docs/mkdocs/docs/api/ordered_map.md b/docs/mkdocs/docs/api/ordered_map.md index 0698fd9e0..efdaa9f7e 100644 --- a/docs/mkdocs/docs/api/ordered_map.md +++ b/docs/mkdocs/docs/api/ordered_map.md @@ -105,7 +105,7 @@ This differs from `#!cpp std::map`, where the same operations are O(log n). If key order matters for objects of that size, consider a container with a lookup index, such as [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) - ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)), as the object type -- see + ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)), as the object type — see [object order](../features/object_order.md). ## Examples diff --git a/docs/mkdocs/docs/css/brand.css b/docs/mkdocs/docs/css/brand.css index b3d61bcfe..8f181f78b 100644 --- a/docs/mkdocs/docs/css/brand.css +++ b/docs/mkdocs/docs/css/brand.css @@ -512,6 +512,27 @@ body:has(.nj-hero) .md-content { .md-typeset .mermaid { overflow-x: auto; } +/* ... and one that is narrower than the column sits in the middle of it */ +.md-typeset .mermaid { + text-align: center; +} + +/* external links (marked by js/external-links.js) get a small "open in new window" icon (Font Awesome + "external-link-alt") in front of them */ +.md-typeset a.nj-external::before { + content: ""; + display: inline-block; + width: .72em; + height: .72em; + margin-right: .3em; + background-color: currentColor; + opacity: .65; + -webkit-mask: var(--nj-external-icon) no-repeat center / contain; + mask: var(--nj-external-icon) no-repeat center / contain; +} +:root { + --nj-external-icon: url('data:image/svg+xml;utf8,'); +} /* ---- polish pass ---- */ diff --git a/docs/mkdocs/docs/features/arbitrary_types.md b/docs/mkdocs/docs/features/arbitrary_types.md index 1bec4a1ff..3c8594281 100644 --- a/docs/mkdocs/docs/features/arbitrary_types.md +++ b/docs/mkdocs/docs/features/arbitrary_types.md @@ -275,7 +275,7 @@ To pick the macro for your own type and get code to start from, answer the quest The `NLOHMANN_DEFINE_TYPE_*`/`NLOHMANN_DEFINE_DERIVED_TYPE_*` macros are generic over any `basic_json` specialization, including `nlohmann::ordered_json`. Simply use `ordered_json` as the target type and members - are serialized in declaration order -- no separate macro or extra code is needed. + are serialized in declaration order — no separate macro or extra code is needed. ```cpp namespace ns { @@ -308,7 +308,7 @@ To pick the macro for your own type and get code to start from, answer the quest There is currently no `NLOHMANN_DEFINE_TYPE_*`-style macro for types that are not [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). This is not an - intentional omission of documentation -- no such macro exists yet; see + intentional omission of documentation — no such macro exists yet; see [How can I use `get()` for non-default constructible/non-copyable types?](#how-can-i-use-get-for-non-default-constructiblenon-copyable-types) for the manual pattern to use instead. @@ -465,7 +465,7 @@ For smart pointers, class hierarchies, `std::variant`, and `std::chrono`, see ## Why can't I convert to/from `std::any`? `std::any` is intentionally excluded from `get()`/generic conversion support, so `get()` and -containers like `std::map` fail to compile by design -- there is no way to know, from a +containers like `std::map` fail to compile by design — there is no way to know, from a `json` value alone, which concrete type to store inside the `std::any`. To work with heterogeneous JSON values, dispatch on the value's type manually and construct the `std::any` (or extract from it) yourself: @@ -497,7 +497,7 @@ what the library does instead. ## Why does `std::wstring` convert or dump incorrectly? -The library assumes UTF-8 encoding internally, so `std::wstring` is not supported out of the box -- see the FAQ +The library assumes UTF-8 encoding internally, so `std::wstring` is not supported out of the box — see the FAQ entry on [wide string handling](../home/faq.md#wide-string-handling) for why, and for a UTF-8 conversion recipe. ## Can I write my own serializer? (Advanced use) diff --git a/docs/mkdocs/docs/features/comments.md b/docs/mkdocs/docs/features/comments.md index 786212c9e..d8a91a244 100644 --- a/docs/mkdocs/docs/features/comments.md +++ b/docs/mkdocs/docs/features/comments.md @@ -11,7 +11,7 @@ This library does not support comments *by default*. It does so for three reason 3. It is dangerous for interoperability if some libraries add comment support while others do not. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this. -However, you can set parameter `ignore_comments` to `#!cpp true` in the [`parse`](../api/basic_json/parse.md) function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace. Combined with [`ignore_trailing_commas`](trailing_commas.md) (also a `parse` parameter), this covers what is commonly referred to as **JSONC** (JSON with Comments, as used e.g. by Visual Studio Code's `.jsonc` files) -- comments and trailing commas, nothing more. This is a different, smaller extension than [JSON5](https://json5.org), which additionally allows unquoted keys, single-quoted strings, and other syntax changes that this library does not support. +However, you can set parameter `ignore_comments` to `#!cpp true` in the [`parse`](../api/basic_json/parse.md) function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace. Combined with [`ignore_trailing_commas`](trailing_commas.md) (also a `parse` parameter), this covers what is commonly referred to as **JSONC** (JSON with Comments, as used e.g. by Visual Studio Code's `.jsonc` files) — comments and trailing commas, nothing more. This is a different, smaller extension than [JSON5](https://json5.org), which additionally allows unquoted keys, single-quoted strings, and other syntax changes that this library does not support. For more information, see [JSON With Commas and Comments (JWCC)](https://nigeltao.github.io/blog/2021/json-with-commas-comments.html). diff --git a/docs/mkdocs/docs/features/conversions.md b/docs/mkdocs/docs/features/conversions.md index c9564a75f..69c2de834 100644 --- a/docs/mkdocs/docs/features/conversions.md +++ b/docs/mkdocs/docs/features/conversions.md @@ -177,7 +177,7 @@ which forces the explicit `get` form and can catch unintended conversions at com `std::optional` from delegating to `get()`, to avoid a constructor ambiguity with `std::optional`'s own converting constructor from `basic_json`. As a result, `static_cast>(json_value)` goes through `std::optional`'s own converting - constructor rather than through `get>()`, which can behave differently -- for example, + constructor rather than through `get>()`, which can behave differently — for example, with a custom `adl_serializer>` specialization. Prefer `get>()`/`get_to()` over `static_cast` for optional types. @@ -193,7 +193,7 @@ which forces the explicit `get` form and can catch unintended conversions at com - The JSON array has **too many** elements: the surplus is **silently discarded**, and no exception is thrown. - The JSON array has **too few** elements: `at` throws - [`out_of_range.401`](../home/exceptions.md#jsonexceptionout_of_range401) for the first missing index -- + [`out_of_range.401`](../home/exceptions.md#jsonexceptionout_of_range401) for the first missing index — an out-of-range error, not a [`type_error`](../home/exceptions.md#type-errors), even though the cause is a shape mismatch. @@ -211,7 +211,7 @@ which forces the explicit `get` form and can catch unintended conversions at com ## Omitting a field when serializing `std::optional` -By default, `to_json` for `std::optional` writes either the value or `#!json null` -- there is no built-in way +By default, `to_json` for `std::optional` writes either the value or `#!json null` — there is no built-in way to make a field disappear from the serialized object entirely when the `std::optional` is `std::nullopt`. Because a specialization of `adl_serializer>` only controls how the *value* is converted (it cannot prevent the containing object's `to_json` from inserting the key in the first place), omission has to be @@ -243,7 +243,7 @@ json j = numbers; // [1,2,3] !!! info "Constructing from a C++20 range view" A `json` array can also be constructed directly from a C++20 range view (`std::ranges::view`), such as the result - of `std::views::filter` or `std::views::transform` -- no intermediate container is needed: + of `std::views::filter` or `std::views::transform` — no intermediate container is needed: ```cpp std::vector nums{1, 2, 37, 42, 21}; diff --git a/docs/mkdocs/docs/features/index.md b/docs/mkdocs/docs/features/index.md index 4715c4762..f9b0f20cc 100644 --- a/docs/mkdocs/docs/features/index.md +++ b/docs/mkdocs/docs/features/index.md @@ -10,7 +10,8 @@ C++ types, and finally serialize it again. understand the `#!cpp {}` vs. `#!cpp []` ambiguity. - [Parsing](parsing/index.md) — read a JSON value from a string, file, or stream, including [JSON Lines](parsing/json_lines.md), [callbacks](parsing/parser_callbacks.md), the - [SAX interface](parsing/sax_interface.md), [error handling](parsing/parse_exceptions.md), and + [SAX interface](parsing/sax_interface.md), [error handling](parsing/parse_exceptions.md), + [large and partial input](parsing/large_and_partial_input.md), and [parsing untrusted input](parsing/untrusted_input.md). - [Zero-copy JSON views](json_view.md) — read a JSON text through a flat index instead of building a `json` tree; strings and numbers stay in the input and are only decoded when needed. @@ -33,6 +34,8 @@ C++ types, and finally serialize it again. - [Converting values](conversions.md) — get values out with [`get`](../api/basic_json/get.md)/[`get_to`](../api/basic_json/get_to.md), and understand implicit conversions. - [Arbitrary types conversions](arbitrary_types.md) — teach the library about your own structs and classes. +- [Recipes for common types](type_recipes.md) — convert smart pointers, `std::variant`, `std::chrono` types, and class + hierarchies, which the library deliberately leaves to you. - [Specializing enum conversion](enum_conversion.md) — map enums to strings instead of integers. ## Serializing values @@ -52,6 +55,7 @@ C++ types, and finally serialize it again. template parameters has to provide. - [Object order](object_order.md) — keep insertion order with [`ordered_json`](../api/ordered_json.md). - [Performance](performance.md) — practical advice on parsing, memory use, serialization, and compile times. +- [Working without exceptions](no_exceptions.md) — what to use when exceptions are unwanted or unavailable. - [Runtime assertions](assertions.md), [supported macros](macros.md), the [`nlohmann` namespace](namespace.md), and [C++ modules](modules.md) — build-time and runtime configuration. diff --git a/docs/mkdocs/docs/features/json_view.md b/docs/mkdocs/docs/features/json_view.md index c15540c1a..653a56512 100644 --- a/docs/mkdocs/docs/features/json_view.md +++ b/docs/mkdocs/docs/features/json_view.md @@ -21,15 +21,15 @@ referenced in place in the source text: a float is converted when it is read, an sequences are decoded, into one shared buffer owned by the document. [`basic_json_view`](../api/basic_json_view/index.md) is a small, trivially copyable handle (two pointers) into that -index. It gives you the read-only, type-inspection part of the `basic_json` interface -- +index. It gives you the read-only, type-inspection part of the `basic_json` interface — [`type()`](../api/basic_json_view/type.md) and the `is_*()` predicates, -[`size()`](../api/basic_json_view/size.md)/[`empty()`](../api/basic_json_view/empty.md) -- as well as element access +[`size()`](../api/basic_json_view/size.md)/[`empty()`](../api/basic_json_view/empty.md) — as well as element access ([`operator[]`](../api/basic_json_view/operator%5B%5D.md), [`at`](../api/basic_json_view/at.md), [`front`](../api/basic_json_view/front.md)/[`back`](../api/basic_json_view/back.md)), lookup ([`find`](../api/basic_json_view/find.md), [`contains`](../api/basic_json_view/contains.md), [`count`](../api/basic_json_view/count.md)), and iteration ([`begin`](../api/basic_json_view/begin.md)/[`end`](../api/basic_json_view/end.md), -[`items`](../api/basic_json_view/items.md)) -- without ever allocating a `basic_json` value. When you do need an +[`items`](../api/basic_json_view/items.md)) — without ever allocating a `basic_json` value. When you do need an actual `basic_json` value for a subtree, [`materialize()`](../api/basic_json_view/materialize.md) builds exactly the one [`parse()`](../api/basic_json/parse.md) would have produced for it. @@ -70,7 +70,7 @@ A document either **borrows** the text it was parsed from, or **owns** its own c [`owns_source()`](../api/basic_json_document/owns_source.md) to find out which happened. [`parse()`](../api/basic_json_document/parse.md) decides this from the value category and type of its argument (an lvalue `#!cpp std::string` is borrowed; an rvalue `#!cpp std::string` is moved in, owned without a copy; a stream is -read into an owned buffer; and so on -- see [`parse`'s Notes](../api/basic_json_document/parse.md#notes) for the full +read into an owned buffer; and so on — see [`parse`'s Notes](../api/basic_json_document/parse.md#notes) for the full table). [`parse_copy()`](../api/basic_json_document/parse_copy.md) always owns a copy, regardless of the input. !!! warning "A borrowed document depends on your buffer" @@ -101,7 +101,7 @@ whenever any of the other conditions above was not met. A view can dangle, exactly like a `#!cpp std::string_view`: nothing stops you from using it after its document is gone. This is deliberate. A view is two pointers and trivially copyable; making it safe (a `#!cpp std::shared_ptr` in the document and a `#!cpp std::weak_ptr` in each view) would make it larger, add reference counting to every copy, -and a `lock()` to every access -- exactly the costs the view exists to avoid. What is caught is the obvious case: +and a `lock()` to every access — exactly the costs the view exists to avoid. What is caught is the obvious case: because a view dies with its document, [`root()`](../api/basic_json_document/root.md) is not callable on a temporary document: `#!cpp auto v = json_document::parse(text).root();` does not compile. Give the document a name first. @@ -123,7 +123,7 @@ document: `#!cpp auto v = json_document::parse(text).root();` does not compile. [`parse()`](../api/basic_json_document/parse.md) accept and reject exactly the same inputs as [`basic_json::accept()`](../api/basic_json/accept.md)/[`basic_json::parse()`](../api/basic_json/parse.md), with the same `ignore_comments` and `ignore_trailing_commas` options. -- **Errors.** A failing parse throws the same exception -- the same id, message, and position -- because on failure +- **Errors.** A failing parse throws the same exception — the same id, message, and position — because on failure the library's own parser is run on the same bytes to produce the diagnostic. Valid input never pays for this, and the replay builds no values: it costs about a lexing pass up to the error. `#!cpp allow_exceptions == false` skips the replay and gives a @@ -169,7 +169,7 @@ document: `#!cpp auto v = json_document::parse(text).root();` does not compile. element access and lookup functions never carry the JSON Pointer path `JSON_DIAGNOSTICS` would otherwise add: the view has no `basic_json` value to point at, so the exception is created without one, regardless of how `BasicJsonType` was built. -- **Ordering comparisons are not provided** by `basic_json_view` -- there is no `#!cpp operator<`. +- **Ordering comparisons are not provided** by `basic_json_view` — there is no `#!cpp operator<`. [`operator==`](../api/basic_json_view/operator_eq.md) and [`operator!=`](../api/basic_json_view/operator_ne.md) are provided, though: two views, or a view and a `BasicJsonType` value, compare equal exactly when [`materialize()`](../api/basic_json_view/materialize.md) or [`parse()`](../api/basic_json/parse.md) would produce @@ -228,36 +228,36 @@ number of distinct keys, or reject duplicates when iterating. `basic_json` value for the conversion: `#!cpp bool`, arithmetic types, `#!cpp std::nullptr_t`, `#!cpp std::string`/other `#!cpp std::basic_string`s (copied once), `basic_json`/`ordered_json` (via [`materialize()`](../api/basic_json_view/materialize.md)), `basic_json_view` itself, `#!cpp std::vector`, and -`#!cpp std::map`/`#!cpp std::unordered_map` with string-like keys. Every other type -- `#!cpp std::list`, -`#!cpp std::pair`, `#!cpp std::array`, enumerations, user types with a `from_json()` -- goes through +`#!cpp std::map`/`#!cpp std::unordered_map` with string-like keys. Every other type — `#!cpp std::list`, +`#!cpp std::pair`, `#!cpp std::array`, enumerations, user types with a `from_json()` — goes through [`materialize()`](../api/basic_json_view/materialize.md)`.get()` instead: the subtree is built into a real `basic_json` value first, exactly as [`parse()`](../api/basic_json/parse.md) would, and converted from there. Two conversions never copy at all: - [`get_string()`](../api/basic_json_view/get_string.md) (equivalently, `#!cpp get()`) returns a - string as a `string_view_t` pointing into the document's [`source()`](../api/basic_json_document/source.md) text -- - or, for a string that contains escape sequences, into the document's own buffer of decoded strings -- instead of + string as a `string_view_t` pointing into the document's [`source()`](../api/basic_json_document/source.md) text — + or, for a string that contains escape sequences, into the document's own buffer of decoded strings — instead of allocating a new `#!cpp std::string`. - [`number_token()`](../api/basic_json_view/number_token.md) returns a number exactly as it was written in the source, e.g. `#!cpp "1.50"`, `#!cpp "1E2"`, or an integer with more digits than any number type holds, instead of rounding it into a `#!cpp double`/`#!cpp int64_t` the way `#!cpp get()` (and [`basic_json::parse()`](../api/basic_json/parse.md)) would. -Both results are only valid as long as the view -- and, for a string with no escapes, the borrowed source text -- is. +Both results are only valid as long as the view — and, for a string with no escapes, the borrowed source text — is. ## Writing a view back [`dump()`](../api/basic_json_view/dump.md) serializes a view directly from the flat index, without ever building a `basic_json` value. An object's members are written in document order, not sorted by key, and *every* occurrence of a -repeated key is written, not only the last one -- the same two ways [iteration](#what-is-different) already differs +repeated key is written, not only the last one — the same two ways [iteration](#what-is-different) already differs from a [`materialize()`](../api/basic_json_view/materialize.md)d value, see [Duplicate keys](#duplicate-keys). `#!cpp materialize().dump()` gives a different result in both respects for a `json_view`. By default, numbers are written the way [`basic_json::dump()`](../api/basic_json/dump.md) would. [`number_format::source`](../api/basic_json_view/number_format.md) instead copies every number exactly as it was -written in the source text -- a price like `#!cpp 19.90`, a long order or account ID with more digits than any number -type holds, or a high-precision coordinate -- something `basic_json` cannot do at all, since parsing already reduces +written in the source text — a price like `#!cpp 19.90`, a long order or account ID with more digits than any number +type holds, or a high-precision coordinate — something `basic_json` cannot do at all, since parsing already reduces a number to its parsed `#!cpp double`/`#!cpp int64_t` value. [`operator<<`](../api/basic_json_view/operator_ltlt.md) writes a view to a stream the way `basic_json`'s does, using @@ -266,14 +266,14 @@ the stream's `width`/`fill` for indentation. ## Editing a document Everything above is read-only: a `json_document`/`json_view` lets you look at a parsed text without copying it, but -not change it. [`basic_json_document`](../api/basic_json_document/index.md) -- more conveniently +not change it. [`basic_json_document`](../api/basic_json_document/index.md) — more conveniently spelled [`json_editable_document`](../api/json_editable_document.md) or -[`ordered_json_editable_document`](../api/ordered_json_editable_document.md) -- also lets you +[`ordered_json_editable_document`](../api/ordered_json_editable_document.md) — also lets you [`set`](../api/basic_json_document/set.md) a value, [`push_back`](../api/basic_json_document/push_back.md) onto or [`insert`](../api/basic_json_document/insert.md) into an array, and [`erase`](../api/basic_json_document/erase.md) an object member or an array element, still without ever building a `basic_json` tree for parts you do not touch. -`#!cpp Editable` defaults to `#!cpp false`, so `json_document`/`ordered_json_document` are unaffected -- they carry +`#!cpp Editable` defaults to `#!cpp false`, so `json_document`/`ordered_json_document` are unaffected — they carry none of the bookkeeping edits need, and calling `set`/`push_back`/`insert`/`erase` on one is a compile error, not a runtime one. @@ -283,7 +283,7 @@ The `#!cpp 19.90` price from [above](#writing-a-view-back) is exactly the kind o or `ordered_json` value in place lossy. Say you parse a configuration file, patch one field, and write it back: - **`json`** re-sorts every key on the way in (`object_t` is a `#!cpp std::map`) and rewrites every number to its - shortest round-trip form on the way out -- a one-field patch turns into a diff that reorders the whole file and + shortest round-trip form on the way out — a one-field patch turns into a diff that reorders the whole file and rewrites `#!cpp 19.90` to `#!cpp 19.9`. - **`ordered_json`** keeps the key order, but still rewrites every number the same way: parsing has already reduced it to a `#!cpp double`/`#!cpp int64_t`, and there is no way back to how it was spelled in the source text. @@ -309,9 +309,9 @@ The patch of the example below (set `"host"`, add `"retries"`) written back by e An editable document keeps both. [`dump()`](../api/basic_json_view/dump.md) of an edited document writes members in -document order -- a member [`set`](../api/basic_json_document/set.md) added goes at the end, exactly where it was +document order — a member [`set`](../api/basic_json_document/set.md) added goes at the end, exactly where it was inserted, and an [`erase`](../api/basic_json_document/erase.md)d member simply leaves a gap: everything around it -keeps its place -- and [`number_format::source`](../api/basic_json_view/number_format.md) keeps the exact spelling +keeps its place — and [`number_format::source`](../api/basic_json_view/number_format.md) keeps the exact spelling of every number an edit did not itself touch; a number an edit *did* touch is written the way [`BasicJsonType::dump()`](../api/basic_json/dump.md) would write it, since there is no source spelling for a brand new value. @@ -330,14 +330,14 @@ new value. ### What stays valid, and what an edit costs -The source text itself is **never written**, and the parsed index never moves -- a value keeps the node it was +The source text itself is **never written**, and the parsed index never moves — a value keeps the node it was parsed into for as long as it is not itself replaced. So every [view](../api/basic_json_view/index.md) taken before an edit, including a previously obtained [`root()`](../api/basic_json_document/root.md), stays valid and, if it still refers to the edited value, sees the edit; a view of a value a later edit drops or replaces just keeps showing what it last held. New values go to storage the document allocates and owns on demand. The one thing an edit does invalidate is the **iterators** taken over an edited array or object: the first time an element is added to it, inserted into it, erased from it, or replaced by a value that spans a different number of nodes, its elements move from the parsed, fixed layout to a growable block of links -so that [`push_back`](../api/basic_json_document/push_back.md) can later grow it in amortized constant time -- +so that [`push_back`](../api/basic_json_document/push_back.md) can later grow it in amortized constant time — existing elements are not touched, but an iterator that was walking the old layout no longer matches. A string obtained with [`get_string()`](../api/basic_json_view/get_string.md) is unaffected either way and stays valid across further @@ -386,13 +386,13 @@ Step through the edits of a small document (the node fields follow the [architec ## Images [`save()`](../api/basic_json_document/save.md) writes a document as an *image*: a byte buffer that -[`load()`](../api/basic_json_document/load.md) reads back into a document without parsing -- no lexing, no building +[`load()`](../api/basic_json_document/load.md) reads back into a document without parsing — no lexing, no building the node index, nothing but copying the nodes and pointing the text and the decoded strings at the image. Where [`parse_copy()`](../api/basic_json_document/parse_copy.md) still has to scan the whole input, [`load()`](../api/basic_json_document/load.md) turns that scan into a copy of the node index alone. -**Why.** A document that is parsed once and then read many times -- a configuration loaded at startup, a template -rendered on every request, a large reference dataset a worker process needs in memory -- pays for parsing once but +**Why.** A document that is parsed once and then read many times — a configuration loaded at startup, a template +rendered on every request, a large reference dataset a worker process needs in memory — pays for parsing once but can amortize [`save()`](../api/basic_json_document/save.md)'s cost across every later load. That makes images useful for a cache: save a document the first time it is parsed (to a file, a shared-memory segment, an in-process cache), and [`load()`](../api/basic_json_document/load.md) it on every later use instead of parsing the source text again. @@ -403,10 +403,10 @@ plus pointers into the received bytes, not a re-parse. **Choosing a check.** [`load()`](../api/basic_json_document/load.md) takes an [`image_check`](../api/basic_json_document/load.md#image_check) that trades validation against speed: `image_check::full` (the default) checks everything the parser itself guarantees, so a checked image is exactly as -safe to read and serialize as a freshly parsed document -- the right choice whenever the image did not come straight +safe to read and serialize as a freshly parsed document — the right choice whenever the image did not come straight from this process's own [`save()`](../api/basic_json_document/save.md), such as a file or a network peer. -`image_check::bounds` only checks structure and bounds -- cheaper, since it skips scanning the text and the decoded -strings -- and fits a cache the process trusts, one it wrote and reads back itself. `image_check::none` skips +`image_check::bounds` only checks structure and bounds — cheaper, since it skips scanning the text and the decoded +strings — and fits a cache the process trusts, one it wrote and reads back itself. `image_check::none` skips validation entirely, for an image trusted as much as the process's own memory. See [`load()`'s Notes](../api/basic_json_document/load.md#notes) for exactly what each level does and does not guarantee. @@ -425,7 +425,7 @@ validation entirely, for an image trusted as much as the process's own memory. S !!! warning "Experimental" The image format is versioned but not yet stable, and may change in an incompatible way before it is declared - stable. It is little-endian only, and tied to the library build that wrote it -- use it to cache a document or to + stable. It is little-endian only, and tied to the library build that wrote it — use it to cache a document or to hand one to another process running the *same* build, not as a long-term storage format; keep the original JSON text if a saved document needs to be readable by a future library version. @@ -441,8 +441,8 @@ either. | **Ownership** | owns every value | owns nothing; you decide what to keep, in your handler | borrows or owns the *text*; the index is always owned by the document | same as `json_document`; edits go to storage the document owns | | **Mutability** | freely mutable | not applicable (a one-shot event stream) | read-only | [`set`](../api/basic_json_document/set.md)/[`push_back`](../api/basic_json_document/push_back.md)/[`insert`](../api/basic_json_document/insert.md)/[`erase`](../api/basic_json_document/erase.md) edit in place; the source text is never rewritten | | **What you get** | a full tree you can read, write, and keep as long as you like | a sequence of callbacks; whatever your handler builds from them | a flat index plus, on demand, [`materialize()`](../api/basic_json_view/materialize.md)d `json`/`ordered_json` values for the parts you actually use | the same, plus [`dump()`](../api/basic_json_view/dump.md) of an edited document that keeps the member order and, with [`number_format::source`](../api/basic_json_view/number_format.md), the spelling of every untouched number | -| **Typical use** | general-purpose JSON handling: config, request/response bodies you build or modify, anything you hold onto | validating or projecting a text into your own data structure without ever holding the whole thing as JSON | large or high-volume input where you only need part of it, or need it repeatedly, and can keep the source text (or a copy) alive for as long as the document lives | a document you read, patch a few fields of, and write back -- a configuration file, for instance -- where the rest of it should come back exactly as it was | -| **Caching/reload** | not applicable -- re-parse, or roll your own serialization | not applicable | [`save()`](../api/basic_json_document/save.md)/[`load()`](../api/basic_json_document/load.md): cache the parsed index as an image and reload it without parsing | same, saving the document's current -- possibly edited -- state | +| **Typical use** | general-purpose JSON handling: config, request/response bodies you build or modify, anything you hold onto | validating or projecting a text into your own data structure without ever holding the whole thing as JSON | large or high-volume input where you only need part of it, or need it repeatedly, and can keep the source text (or a copy) alive for as long as the document lives | a document you read, patch a few fields of, and write back — a configuration file, for instance — where the rest of it should come back exactly as it was | +| **Caching/reload** | not applicable — re-parse, or roll your own serialization | not applicable | [`save()`](../api/basic_json_document/save.md)/[`load()`](../api/basic_json_document/load.md): cache the parsed index as an image and reload it without parsing | same, saving the document's current — possibly edited — state |

Each column is one way to work with JSON in this library, and each row compares one property of them.

diff --git a/docs/mkdocs/docs/features/merge_patch.md b/docs/mkdocs/docs/features/merge_patch.md index 0d2151835..ceafe8724 100644 --- a/docs/mkdocs/docs/features/merge_patch.md +++ b/docs/mkdocs/docs/features/merge_patch.md @@ -12,18 +12,61 @@ easier to read and write for object-shaped documents. The function [`merge_diff`](../api/basic_json/merge_diff.md) creates a merge patch that changes one JSON value into another. -The example below shows every rule in one patch, member by member: +The example below applies one patch to one document. Here is the document before: + +```json +{ + "title": "Goodbye!", + "author": { + "givenName": "John", + "familyName": "Doe" + }, + "tags": ["example", "sample"], + "content": "This will be unchanged" +} +``` + +This is the patch: + +```json +{ + "title": "Hello!", + "phoneNumber": "+01-123-456-7890", + "author": { + "familyName": null + }, + "tags": ["example"] +} +``` + +And this is the document after applying it: + +```json +{ + "title": "Hello!", + "author": { + "givenName": "John" + }, + "tags": ["example"], + "content": "This will be unchanged", + "phoneNumber": "+01-123-456-7890" +} +``` + +The table goes through the members one by one. "Member" is the name of an object member in the patch (and in the +document); it is not a [JSON Pointer](json_pointer.md) and nothing of it is passed to the function: the whole patch is +passed to [`merge_patch`](../api/basic_json/merge_patch.md).
-| Rule | Key | Target | Patch | Result | -|------|-----|--------|-------|--------| +| Rule | Member | Before | Patch | After | +|------|--------|--------|-------|-------| | change value | `title` | `#!json "Goodbye!"` | `#!json "Hello!"` | `#!json "Hello!"` | -| add key | `phoneNumber` | (no key) | `#!json "+01-123-456-7890"` | `#!json "+01-123-456-7890"` | -| null removes key | `author.familyName` | `#!json "Doe"` | `#!json null` | (removed) | +| add key | `phoneNumber` | (no member) | `#!json "+01-123-456-7890"` | `#!json "+01-123-456-7890"` | | object merges recursively | `author` | `#!json {"givenName": "John", "familyName": "Doe"}` | `#!json {"familyName": null}` | `#!json {"givenName": "John"}` | +| null removes key | `familyName` inside `author` | `#!json "Doe"` | `#!json null` | (removed) | | array replaced whole | `tags` | `#!json ["example", "sample"]` | `#!json ["example"]` | `#!json ["example"]` | -| unchanged key | `content` | `#!json "This will be unchanged"` | (no key) | `#!json "This will be unchanged"` | +| unchanged key | `content` | `#!json "This will be unchanged"` | (no member) | `#!json "This will be unchanged"` |
diff --git a/docs/mkdocs/docs/features/parsing/index.md b/docs/mkdocs/docs/features/parsing/index.md index ebccf4cf4..901626952 100644 --- a/docs/mkdocs/docs/features/parsing/index.md +++ b/docs/mkdocs/docs/features/parsing/index.md @@ -36,7 +36,7 @@ json data = json::parse(f); ``` The input must be encoded in UTF-8; other encodings are not supported. The exception is wide-character input, which -is read as UTF-16 or UTF-32 -- depending on the character type -- and converted to UTF-8; see the +is read as UTF-16 or UTF-32 — depending on the character type — and converted to UTF-8; see the [`parse`](../../api/basic_json/parse.md) page for an example. A single input may contain only one JSON value. Inputs consisting of multiple values separated by newlines are handled by the [JSON Lines](json_lines.md) format; input that arrives in chunks or contains several values is covered in diff --git a/docs/mkdocs/docs/features/parsing/json_lines.md b/docs/mkdocs/docs/features/parsing/json_lines.md index a883daed6..f7f525e57 100644 --- a/docs/mkdocs/docs/features/parsing/json_lines.md +++ b/docs/mkdocs/docs/features/parsing/json_lines.md @@ -61,7 +61,7 @@ JSON Lines input with more than one value is treated as invalid JSON by the [`pa } ``` - A value that is a number must be followed by whitespace -- see the [notes](../../api/operator_gtgt.md#notes) of + A value that is a number must be followed by whitespace — see the [notes](../../api/operator_gtgt.md#notes) of `operator>>` for details. ## See also diff --git a/docs/mkdocs/docs/features/parsing/parser_callbacks.md b/docs/mkdocs/docs/features/parsing/parser_callbacks.md index 35d9f3711..187f10bab 100644 --- a/docs/mkdocs/docs/features/parsing/parser_callbacks.md +++ b/docs/mkdocs/docs/features/parsing/parser_callbacks.md @@ -102,7 +102,7 @@ was called: The JSON specification leaves the handling of objects with repeated keys up to the implementation. As described in [`object_t`](../../api/basic_json/object_t.md#behavior), it is unspecified which value for a repeated key ends up in -the resulting `#!c json` value -- once parsing has produced that value, the duplicate is already gone, because object +the resulting `#!c json` value — once parsing has produced that value, the duplicate is already gone, because object storage maps each key to a single value. If duplicate keys should instead be treated as an error, a parser callback can detect them while the object is still being read, before that ambiguity ever applies. @@ -129,7 +129,7 @@ This approach has three limitations: maintaining a stack of the enclosing keys and array indices in the callback as well. A [SAX interface](sax_interface.md) does not lift the position limitation: its `key` function receives no position -either -- only `parse_error` is passed the byte position. +either — only `parse_error` is passed the byte position. ## Recipe: streaming a large homogeneous array diff --git a/docs/mkdocs/docs/features/parsing/untrusted_input.md b/docs/mkdocs/docs/features/parsing/untrusted_input.md index 9f29dddc3..e89a7a7a3 100644 --- a/docs/mkdocs/docs/features/parsing/untrusted_input.md +++ b/docs/mkdocs/docs/features/parsing/untrusted_input.md @@ -1,7 +1,7 @@ # Parsing Untrusted Input -This page is for applications that parse JSON -- or one of the supported [binary formats](../binary_formats/index.md) -(BJData, BON8, BSON, CBOR, MessagePack, UBJSON) -- from a source they do not fully control, such as a network +This page is for applications that parse JSON — or one of the supported [binary formats](../binary_formats/index.md) +(BJData, BON8, BSON, CBOR, MessagePack, UBJSON) — from a source they do not fully control, such as a network connection, an uploaded file, or another process. It summarizes what the library already does for such input and what remains the caller's responsibility, linking to the pages that cover each aspect in detail rather than repeating them. @@ -50,12 +50,12 @@ stack, however deeply it is nested. [SAX handler](sax_interface.md) (for the JSON parser or a binary format alike) and throwing once your limit is exceeded. -Once a value has been parsed, operations that walk it recursively -- serializing it with +Once a value has been parsed, operations that walk it recursively — serializing it with [`dump`](../../api/basic_json/dump.md), hashing it, copying it, comparing two values with `#!cpp ==`, `#!cpp <`, or (in C++20) `#!cpp <=>`, merging with [`update`](../../api/basic_json/update.md), applying a [`merge_patch`](../../api/basic_json/merge_patch.md), creating a patch with [`diff`](../../api/basic_json/diff.md) or [`merge_diff`](../../api/basic_json/merge_diff.md), [`flatten`](../../api/basic_json/flatten.md), and the binary -writers (`to_cbor`, `to_msgpack`, ...) -- descend at most 128 levels on the call stack and continue +writers (`to_cbor`, `to_msgpack`, ...) — descend at most 128 levels on the call stack and continue below that with an explicit stack instead, so none of them can exhaust the stack either, however deeply the value is nested. Destroying a value (its destructor) never recurses at all, regardless of nesting depth, for the same reason. @@ -63,12 +63,12 @@ nested. Destroying a value (its destructor) never recurses at all, regardless of The library does not limit the overall size of a JSON text; a value nested or wide enough will use memory proportional to the input. If you parse untrusted input of unbounded size, check the size of the file or stream -yourself before -- or while -- handing it to `parse()`. +yourself before — or while — handing it to `parse()`. For the binary formats, an announced size is never trusted outright: - Reading a string or binary value copies the input in bounded 4096-byte chunks and grows the result as bytes are - actually consumed, rather than allocating the announced length up front -- a truncated input runs out of bytes + actually consumed, rather than allocating the announced length up front — a truncated input runs out of bytes (reported as a parse error) instead of triggering an oversized allocation. - When an array announces its number of elements and the array container supports `reserve()` (as `#!cpp std::vector`, the default, does), the library reserves storage for at most 16384 of them upfront, regardless of how large the @@ -91,7 +91,7 @@ Invalid UTF-8 is rejected while parsing, not just while serializing: A `#!cpp '\0'` (NUL) byte *inside* a quoted JSON string is always rejected (it must be escaped as `\u0000`). A NUL byte *outside* of a string is different: by default it is silently treated as the end of the input, so trailing bytes after -it -- including further, otherwise well-formed JSON -- are silently ignored rather than rejected. Since untrusted input +it — including further, otherwise well-formed JSON — are silently ignored rather than rejected. Since untrusted input that happens to embed a NUL is a way to make part of it disappear without a parse error, see the [FAQ entry](../../home/faq.md#nul-bytes-in-the-input) and consider defining [`JSON_STRICT_NUL_HANDLING`](../../api/macros/json_strict_nul_handling.md) to `1` to reject a NUL byte like any other @@ -116,7 +116,7 @@ silently resolving them one way or another, see the ## Numbers -A number whose value cannot be represented -- for instance `1E1000`, which overflows `double` -- is rejected while +A number whose value cannot be represented — for instance `1E1000`, which overflows `double` — is rejected while parsing as [`out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406) rather than silently becoming infinity. An integer that is syntactically valid but does not fit the 64-bit integer types is not rejected; it is instead stored as a `double`, which may lose precision for very large values. See @@ -139,7 +139,7 @@ conforming JSON consumers is exactly what the default rejects. [SAX handler](sax_interface.md); the library bounds the call stack but not memory use. - Bound the size of the input itself before parsing, independent of the library's own bounded allocations for binary format lengths. -- Decide up front how you want a string with invalid UTF-8 -- from any source, not only parsing -- to be serialized +- Decide up front how you want a string with invalid UTF-8 — from any source, not only parsing — to be serialized (`strict`, `replace`, or `ignore`), rather than discovering it from an uncaught `type_error.316`. - If a stray NUL byte silently truncating trailing input is a problem for your input format, define `JSON_STRICT_NUL_HANDLING`. diff --git a/docs/mkdocs/docs/features/performance.md b/docs/mkdocs/docs/features/performance.md index a49a529e0..ffea9c215 100644 --- a/docs/mkdocs/docs/features/performance.md +++ b/docs/mkdocs/docs/features/performance.md @@ -6,7 +6,7 @@ first. If a hard real-time budget or the last percent of throughput matters more [faster, more specialized library](https://github.com/miloyip/nativejson-benchmark#parsing-time) may be a better fit. That said, how you use this library still makes a measurable difference. This page collects practical, code-verified -techniques for reducing time, memory, and compile-time cost -- without repeating the detailed pages it links to. +techniques for reducing time, memory, and compile-time cost — without repeating the detailed pages it links to. ## Parsing input @@ -14,8 +14,8 @@ techniques for reducing time, memory, and compile-time cost -- without repeating `#!cpp FILE*` (see [Parsing](parsing/index.md#input)). Internally, every input is wrapped in an [input adapter](../home/architecture.md#input-adapters), and not all adapters are equally fast. -For inputs backed by contiguous, single-byte memory -- a `#!cpp std::string`, a `#!cpp std::vector`, a string -literal, or a pointer range -- the library uses `iterator_input_adapter`, wrapped in a raw pointer so the fast paths +For inputs backed by contiguous, single-byte memory — a `#!cpp std::string`, a `#!cpp std::vector`, a string +literal, or a pointer range — the library uses `iterator_input_adapter`, wrapped in a raw pointer so the fast paths below apply on every supported standard. This adapter exposes two optimizations the lexer detects at compile time: - it can reconstruct already-consumed input on demand for error messages, instead of copying every character as it is @@ -69,7 +69,7 @@ a DOM, three alternatives avoid building it: `basic_json` values. - Pass a [parser callback](parsing/parser_callbacks.md) to `parse`. This still builds a DOM, but the callback can discard finished elements as soon as they are handled, so memory usage stays bounded by one element (plus the - unparsed remainder of the input) instead of the whole document -- see the [recipe for streaming a large homogeneous + unparsed remainder of the input) instead of the whole document — see the [recipe for streaming a large homogeneous array](parsing/parser_callbacks.md#recipe-streaming-a-large-homogeneous-array). - Parse into a [`json_document`](json_view.md) (`#!cpp `) instead of a `basic_json`. It keeps the input text and builds a flat index of 16 bytes per value; strings and floating-point numbers are not copied, but @@ -85,15 +85,15 @@ at a time, and a malformed line does not invalidate lines already processed. ## Binary formats JSON text is not a compact format. If the data is only exchanged between programs (not read by humans), the -[binary formats](binary_formats/index.md) -- BJData, BON8, BSON, CBOR, MessagePack, and UBJSON -- encode the same +[binary formats](binary_formats/index.md) — BJData, BON8, BSON, CBOR, MessagePack, and UBJSON — encode the same values more compactly, which reduces both the bytes transferred and, for most of them, the work needed to parse them back. The [size comparison](binary_formats/index.md#sizes) on that page, measured against minified JSON for four reference documents, shows the effect varies a lot by document shape: CBOR and MessagePack come out at 50.5% of the minified JSON size for the numeric-array-heavy `canada.json`, but only around 87-88% for the string-heavy `jeopardy.json`, where there is less numeric data to encode more compactly. BON8 is the most compact option in that comparison for text-heavy documents (63.5%-87.5%), at the cost of an -[incomplete serializer](binary_formats/index.md#completeness) (no unsigned integers above int64). Which format -- and -whether it is worth the loss of human readability at all -- depends on the actual data; see the +[incomplete serializer](binary_formats/index.md#completeness) (no unsigned integers above int64). Which format — and +whether it is worth the loss of human readability at all — depends on the actual data; see the [comparison tables](binary_formats/index.md#comparison) before choosing one.
@@ -113,7 +113,7 @@ The default [`json`](../api/json.md) type stores object keys in a `#!cpp std::ma insertion, and erasure, at the cost of sorting keys alphabetically rather than preserving insertion order (see [Object Order](object_order.md)). [`ordered_json`](../api/ordered_json.md) uses [`nlohmann::ordered_map`](../api/ordered_map.md) instead, a `#!cpp std::vector`-backed container with no lookup index: -every key-based operation is a **linear scan**, so building an object of `n` distinct keys costs **O(n²)** in total -- +every key-based operation is a **linear scan**, so building an object of `n` distinct keys costs **O(n²)** in total — this applies equally to inserting keys one by one and to parsing an object, since the parser inserts each key as it is read. The [measurements on the `ordered_map` page](../api/ordered_map.md#complexity) show this is negligible at typical object sizes (2000 keys: 0.7 ms for `json` vs. 3.6 ms for `ordered_json`, a 5x factor) but grows @@ -131,7 +131,7 @@ may not be acceptable. The library's [`ObjectType` template parameter](types/tem set to a different container instead: `#!cpp nlohmann::fifo_map` keeps insertion order with a real lookup index (avoiding the quadratic cost), while `#!cpp std::unordered_map`, `#!cpp boost::unordered_flat_map`, `#!cpp absl::flat_hash_map`, and similar hash maps trade insertion order for average-case constant-time lookup (through -an adapter, since their template argument order does not match what `basic_json` expects) -- see +an adapter, since their template argument order does not match what `basic_json` expects) — see [Object Order](object_order.md#alternative-behavior-preserve-insertion-order) for the full list. ## Avoiding copies @@ -146,13 +146,13 @@ an adapter, since their template argument order does not match what `basic_json` - **Access without copying.** [`get()`](../api/basic_json/get.md) returns a copy of the stored value converted to `T`. When a reference or pointer to the value already stored inside the `basic_json` is enough, [`get_ref()`](../api/basic_json/get_ref.md) and [`get_ptr()`](../api/basic_json/get_ptr.md) access it directly: - both pages state, word for word, "No copies are made." -- at the cost of that reference or pointer becoming invalid + both pages state, word for word, "No copies are made." — at the cost of that reference or pointer becoming invalid once the underlying value changes. - **Iterate by reference.** `#!cpp basic_json::iterator::operator*()` returns a `reference` (an alias for `#!cpp basic_json&`), but a range-based for loop with a by-value loop variable (`#!cpp for (auto el : j)`) still copies each element, because plain `#!cpp auto` drops the reference. Write `#!cpp for (const auto& el : j)` (or `#!cpp auto&` for a mutable loop), and use [`items()`](../api/basic_json/items.md) the same way when the key is - needed too -- its own examples use `#!cpp for (auto& el : j.items())`. + needed too — its own examples use `#!cpp for (auto& el : j.items())`. - **Construct in place.** [`emplace_back()`](../api/basic_json/emplace_back.md) (arrays, amortized constant time) and [`emplace()`](../api/basic_json/emplace.md) (objects, logarithmic in the size of the container for `json`) forward their arguments directly to a `basic_json` constructor, rather than requiring a temporary value to be @@ -161,13 +161,13 @@ an adapter, since their template argument order does not match what `basic_json` in instead of copying it. - **Skip the bounds check when it is redundant.** [`at()`](../api/basic_json/at.md) and [`operator[]`](../api/basic_json/operator%5B%5D.md) have the same complexity (constant for a valid array index, - logarithmic for an object key in `json`) -- the difference is that `at()` additionally checks the key or index and + logarithmic for an object key in `json`) — the difference is that `at()` additionally checks the key or index and throws if it is invalid, while `operator[]` does not (see [unchecked access](element_access/unchecked_access.md) and [checked access](element_access/checked_access.md)). Prefer `operator[]` when the surrounding code has already established that the access is valid. - **Reserve array capacity.** `basic_json` has no public `reserve()`, but when building a large array incrementally with a known final size, [`get_ref()`](../api/basic_json/get_ref.md) exposes the underlying - `#!cpp array_t` so it can be reserved directly -- see + `#!cpp array_t` so it can be reserved directly — see ["reserving array capacity"](element_access/unchecked_access.md#performance-reserving-array-capacity) for the one-line recipe. @@ -200,7 +200,7 @@ an adapter, since their template argument order does not match what `basic_json` (word for word from the page); any non-negative `indent` pretty-prints instead, which is more readable but produces more bytes and more work. `dump()` builds and returns a complete `#!cpp string_t` containing the whole serialization. [`operator<<`](../api/operator_ltlt.md) writes directly to a `#!cpp std::ostream` instead, through the same -serializer, but without ever materializing that intermediate string -- so if the destination is a stream (a file, or +serializer, but without ever materializing that intermediate string — so if the destination is a stream (a file, or `#!cpp std::cout`), `#!cpp os << j;` avoids the allocation and copy that `#!cpp os << j.dump();` would incur for large values. @@ -211,7 +211,7 @@ while it is in use: - [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) adds a JSON Pointer to exception messages, pointing at the value that triggered the exception. Quoting the page directly: "enabling this macro increases the size of every - JSON value by one pointer and adds some runtime overhead" -- every value gains a parent pointer that has to be kept + JSON value by one pointer and adds some runtime overhead" — every value gains a parent pointer that has to be kept up to date as the document is built and modified. - [`JSON_DIAGNOSTIC_POSITIONS`](../api/macros/json_diagnostic_positions.md) adds [`start_pos()`](../api/basic_json/start_pos.md) and [`end_pos()`](../api/basic_json/end_pos.md), the byte offsets a @@ -228,7 +228,7 @@ untrusted input, or in a debug build), and keep them off in a release build that [`basic_json`](../api/basic_json/index.md), [`json`](../api/json.md), [`ordered_json`](../api/ordered_json.md), [`json_pointer`](../api/json_pointer/index.md), and [`adl_serializer`](../api/adl_serializer/index.md), pulling in only a handful of lightweight standard headers instead of the full `json.hpp`. A header that only needs to *name* -`nlohmann::json` -- in a function signature or a class member declaration, for instance -- can include `json_fwd.hpp` +`nlohmann::json` — in a function signature or a class member declaration, for instance — can include `json_fwd.hpp` and leave `#!cpp #include ` to the source files that actually parse, build, or serialize values, the same way a project would forward-declare any other heavy class to keep it out of widely-included headers: @@ -249,8 +249,8 @@ nlohmann::json my_type::config() const { /* ... */ } ``` One caveat: ABI-affecting macros such as `JSON_DIAGNOSTICS` and `JSON_DIAGNOSTIC_POSITIONS` are encoded into the -library's [inline namespace name](namespace.md#limitations). Every translation unit -- whether it includes -`json_fwd.hpp` or the full header -- must define them the same way, or linking fails with undefined references +library's [inline namespace name](namespace.md#limitations). Every translation unit — whether it includes +`json_fwd.hpp` or the full header — must define them the same way, or linking fails with undefined references instead of a compile error. If I/O support is not needed at all, [`JSON_NO_IO`](../api/macros/json_no_io.md) excludes ``, ``, diff --git a/docs/mkdocs/docs/features/types/template_parameters.md b/docs/mkdocs/docs/features/types/template_parameters.md index 087a81432..f89d2b161 100644 --- a/docs/mkdocs/docs/features/types/template_parameters.md +++ b/docs/mkdocs/docs/features/types/template_parameters.md @@ -1,7 +1,7 @@ # Template Parameter Requirements Class [`basic_json`](../../api/basic_json/index.md) is configurable through eleven template parameters. The library -never formally states what a type passed for one of these parameters has to provide -- the requirements are implied by +never formally states what a type passed for one of these parameters has to provide — the requirements are implied by the way the library uses the resulting [`object_t`](../../api/basic_json/object_t.md), [`array_t`](../../api/basic_json/array_t.md), [`string_t`](../../api/basic_json/string_t.md), etc. This page collects these requirements so they do not have to be discovered by trial and error. Each section lists the concrete types @@ -16,9 +16,9 @@ To change a single template parameter and keep the others, use the member alias Requirements are split into two groups: -- **Always required** -- needed to instantiate `basic_json` at all, or needed by functions that virtually every program +- **Always required** — needed to instantiate `basic_json` at all, or needed by functions that virtually every program uses (construction, element access, [`dump`](../../api/basic_json/dump.md)). -- **Required for ...** -- only needed when a particular part of the API is instantiated. Member function templates are +- **Required for ...** — only needed when a particular part of the API is instantiated. Member function templates are only instantiated when they are used, so a type may be perfectly usable even though it does not satisfy these requirements, as long as the corresponding functions are never called. @@ -56,8 +56,8 @@ Requirements are split into two groups: !!! warning "Third-party containers and incomplete types" - `object_t` is instantiated inside the definition of `basic_json` -- it is probed for a `key_compare` member to - form [`object_comparator_t`](../../api/basic_json/object_comparator_t.md) -- i.e. while `basic_json` is still an + `object_t` is instantiated inside the definition of `basic_json` — it is probed for a `key_compare` member to + form [`object_comparator_t`](../../api/basic_json/object_comparator_t.md) — i.e. while `basic_json` is still an incomplete type. `#!cpp std::map` is required by the standard to support incomplete mapped types; most third-party maps are not, and inspecting the mapped type at class scope (for instance with `#!cpp std::is_trivially_move_assignable`) makes them unusable as `ObjectType`, no matter how their template @@ -65,7 +65,7 @@ Requirements are split into two groups: `robin_hood::unordered_node_map`, `folly::F14FastMap`, and `eastl::hash_map`. `array_t` is only *named* in the class definition and is not instantiated until `basic_json` is complete, so an - `ArrayType` that inspects its value type at class scope is generally fine -- `boost::container::small_vector` and + `ArrayType` that inspects its value type at class scope is generally fine — `boost::container::small_vector` and `static_vector` both reject incomplete value types yet work here. `absl::InlinedVector` is the exception: the `#!cpp std::is_trivially_move_assignable` it evaluates while instantiating itself re-enters the library's own trait machinery mid-instantiation. @@ -93,7 +93,7 @@ i.e., the template arguments follow the order and meaning of `std::map`. - The template must be usable with **four** type arguments in the order shown above. The third argument is a **comparator**; containers that expect something else in this position (e.g., a hash function) need an alias template - or wrapper -- see [Notes](#notes). + or wrapper — see [Notes](#notes). - An optional member type `key_compare`. If it is present it becomes [`object_comparator_t`](../../api/basic_json/object_comparator_t.md); otherwise [`default_object_comparator_t`](../../api/basic_json/default_object_comparator_t.md) is used. @@ -116,7 +116,7 @@ i.e., the template arguments follow the order and meaning of `std::map`. semantics; multimaps cannot be used. - The type must be swappable (via `std::swap` or an ADL `swap`). - The comparison operators `==` and `<`; `!=`, `<=`, `>`, and `>=` are derived from them. Where the library uses - three-way comparison (C++20), `==` and `<=>` are required **instead** -- the six two-way operators do not satisfy + three-way comparison (C++20), `==` and `<=>` are required **instead** — the six two-way operators do not satisfy it. They implement [`basic_json`'s comparison operators](../../api/basic_json/operator_eq.md). ### Required for heterogeneous key lookup @@ -200,7 +200,7 @@ object keys are serialized by [`dump`](../../api/basic_json/dump.md) and visited With [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md) enabled, the library detects insertion-ordered maps by probing for a `capacity()` member function (`nlohmann::ordered_map` inherits it from `std::vector`) and refreshes all parent pointers after every insertion. An `ObjectType` that happens to have a `capacity()` member is therefore treated -conservatively -- this is correct, but slower. +conservatively — this is correct, but slower. #### Key order and duplicate keys @@ -211,7 +211,7 @@ The library does not sort or de-duplicate keys itself; the behavior described in `docs/mkdocs/docs/examples/custom_object_type.hpp` wraps a private `#!cpp std::map` and satisfies every requirement above. It does not define `key_compare`, so `object_comparator_t` falls back to - [`default_object_comparator_t`](../../api/basic_json/default_object_comparator_t.md) -- a good starting point for + [`default_object_comparator_t`](../../api/basic_json/default_object_comparator_t.md) — a good starting point for a custom `ObjectType`. ```cpp @@ -305,7 +305,7 @@ using array_t = ArrayType>; !!! tip "Reference implementation" `docs/mkdocs/docs/examples/custom_array_type.hpp` wraps a private `#!cpp std::vector` and satisfies every - requirement above -- a good starting point for a custom `ArrayType`. + requirement above — a good starting point for a custom `ArrayType`. ```cpp --8<-- "examples/custom_array_type.hpp" @@ -385,13 +385,13 @@ using array_t = ArrayType>; ### Required for JSON Pointer, `flatten`, and `diff` -- A static member `npos` and the member function `find_first_of(char, size_type)` -- together with `data()`, +- A static member `npos` and the member function `find_first_of(char, size_type)` — together with `data()`, `reserve(n)`, and `append(const char*, size_type)` they implement the escaping and unescaping of reference tokens described in RFC 6901. Neither `find(const StringType&, size_type)`, nor `substr(pos, count)`, nor `replace(pos, count, const StringType&)` is required. - `empty()`. -- `resize(n)` (one argument) -- used by `to_string` to size the result before the reference tokens are copied into it. -- `begin()` and `end()` -- used by +- `resize(n)` (one argument) — used by `to_string` to size the result before the reference tokens are copied into it. +- `begin()` and `end()` — used by [`operator[](const json_pointer&)`](../../api/basic_json/operator%5B%5D.md) to decide whether a reference token denotes an array index. @@ -417,7 +417,7 @@ using array_t = ArrayType>; | `#!cpp std::pmr::string` | see the warning below before relying on the memory resource | | `boost::container::string` | needs a user-supplied `#!cpp std::hash` specialization (Boost provides `boost::hash` instead) | | `folly::fbstring` | requires C++20, see the note above | -| `eastl::string` | needs a user-supplied `#!cpp std::hash` and an ADL `int_to_string` (it is not assignable from a `#!cpp std::string`); [`parse`](../../api/basic_json/parse.md) does not accept it directly -- pass a character range or a `#!cpp std::string` | +| `eastl::string` | needs a user-supplied `#!cpp std::hash` and an ADL `int_to_string` (it is not assignable from a `#!cpp std::string`); [`parse`](../../api/basic_json/parse.md) does not accept it directly — pass a character range or a `#!cpp std::string` | | a custom string class in a user-defined namespace | if the requirements above are met | ### Types that cannot be used @@ -435,13 +435,13 @@ using array_t = ArrayType>; allocation and has to be stateless (see [`AllocatorType`](#allocatortype)), and string values the library creates are constructed with their own default allocator. So: - - Every string the library itself produces -- from [`parse`](../../api/basic_json/parse.md), from - [`dump`](../../api/basic_json/dump.md), or by default construction -- allocates from + - Every string the library itself produces — from [`parse`](../../api/basic_json/parse.md), from + [`dump`](../../api/basic_json/dump.md), or by default construction — allocates from `#!cpp std::pmr::get_default_resource()`. - **Copying** an arena-backed string into a value silently drops its memory resource: the copy lands on the default resource, because `#!cpp std::pmr::polymorphic_allocator` does not propagate on copy construction. Nothing warns about this. - - **Moving** one in does keep it, and later growth still allocates from that arena -- but it does not survive a + - **Moving** one in does keep it, and later growth still allocates from that arena — but it does not survive a copy of the enclosing `basic_json`. - Passing `#!cpp std::pmr::polymorphic_allocator` as `AllocatorType` does not work around any of this; it does not compile. @@ -452,7 +452,7 @@ using array_t = ArrayType>; !!! tip "Reference implementation" `docs/mkdocs/docs/examples/custom_string_type.hpp` wraps a private `#!cpp std::string` and satisfies every - requirement above -- a good starting point for a custom `StringType`. The unit test + requirement above — a good starting point for a custom `StringType`. The unit test `tests/src/unit-alt-string.cpp` contains a more thorough variant, `alt_string`, exercised against a larger part of the API. @@ -480,8 +480,8 @@ using array_t = ArrayType>; - A literal type that is trivially default-constructible, trivially copyable, and trivially destructible; otherwise the union's special member functions are deleted. -- **Implicitly** convertible from `#!cpp bool` -- an `#!cpp explicit` constructor is not enough, because the - `to_json` overload for a custom `BooleanType` is constrained on `#!cpp std::is_convertible` -- and contextually +- **Implicitly** convertible from `#!cpp bool` — an `#!cpp explicit` constructor is not enough, because the + `to_json` overload for a custom `BooleanType` is constrained on `#!cpp std::is_convertible` — and contextually convertible to `#!cpp bool` (here an `#!cpp explicit operator bool` is fine). - Comparison operators `==`, `!=`, `<`, `<=`, `>`, `>=` (or `<=>`). - Convertible from and to `#!cpp bool` through the serializer, because @@ -492,7 +492,7 @@ There is little reason to use anything other than `#!cpp bool` here. ### Compatible types `#!cpp bool` is the only usable choice. Another trivially copyable type that is implicitly convertible to and from -`#!cpp bool` -- `#!cpp std::uint8_t`, say -- does compile, and JSON booleans still round-trip, but the type then +`#!cpp bool` — `#!cpp std::uint8_t`, say — does compile, and JSON booleans still round-trip, but the type then serves as both `boolean_t` and an ordinary integer: `basic_json` can no longer be constructed or assigned from a `#!cpp std::uint8_t` at all (the boolean and unsigned-integer `to_json` overloads become ambiguous), and [`get()`](../../api/basic_json/get.md) on a number throws @@ -506,7 +506,7 @@ Both types are stored **directly** inside `basic_json`'s union. - `#!cpp std::is_integral` must be satisfied: `NumberIntegerType` must be a **signed** integer type, `NumberUnsignedType` an **unsigned** integer type or the same type as `NumberIntegerType` (see - [below](#same-type-for-both)). Class types are not supported -- among others, the constructors taking integer values + [below](#same-type-for-both)). Class types are not supported — among others, the constructors taking integer values are constrained on `#!cpp std::is_integral`. - Trivially default-constructible, trivially copyable, and trivially destructible (union member). - `#!cpp std::numeric_limits` must be specialized for both types. @@ -636,7 +636,7 @@ process deeply nested values without recursion. ### Always required -- The template must accept **two** type arguments. It does not have to give the second one a default -- `basic_json` +- The template must accept **two** type arguments. It does not have to give the second one a default — `basic_json` declares the parameter as `#!cpp template class JSONSerializer`, so uses such as `#!cpp JSONSerializer` inside the library supply `#!cpp void` themselves. The second parameter exists so that partial specializations can be constrained by SFINAE. @@ -669,7 +669,7 @@ using binary_t = nlohmann::byte_container_with_subtype; ### Always required -- A non-`final` class type -- [`byte_container_with_subtype`](../../api/byte_container_with_subtype/index.md) derives +- A non-`final` class type — [`byte_container_with_subtype`](../../api/byte_container_with_subtype/index.md) derives from it publicly. - A member type `value_type` that is **exactly one byte** wide (e.g., `#!cpp std::uint8_t`, `#!cpp char`, or `#!cpp std::byte`). Readers and writers reinterpret the container's storage as raw bytes, so a wider `value_type` is @@ -697,7 +697,7 @@ such a container to a `basic_json` value. !!! tip "Reference implementation" `docs/mkdocs/docs/examples/custom_binary_type.hpp` wraps a private `#!cpp std::vector` and satisfies - every requirement above -- a good starting point for a custom `BinaryType`. + every requirement above — a good starting point for a custom `BinaryType`. ```cpp --8<-- "examples/custom_binary_type.hpp" @@ -733,7 +733,7 @@ such a container to a `basic_json` value. | `QByteArray` | no `empty()` (it spells that `isEmpty()`); its `insert` takes an index rather than an iterator; and it converts to `string_t`, which makes `to_json` ambiguous between a string and a binary value | | `#!cpp std::string` | `binary_t::container_type` and `string_t` would be the same type, so the two [`swap`](../../api/basic_json/swap.md) overloads collide and `basic_json` cannot be instantiated at all | | `#!cpp std::deque` | storage is not contiguous, so there is no `data()` | -| containers whose `value_type` is wider than one byte | see above -- accepted by the compiler, wrong at runtime | +| containers whose `value_type` is wider than one byte | see above — accepted by the compiler, wrong at runtime | ## `CustomBaseClass` diff --git a/docs/mkdocs/docs/home/debugging.md b/docs/mkdocs/docs/home/debugging.md index 199b7db06..d471213ee 100644 --- a/docs/mkdocs/docs/home/debugging.md +++ b/docs/mkdocs/docs/home/debugging.md @@ -50,7 +50,7 @@ Defining [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) before includin `type_error`/`out_of_range`-style exceptions with a JSON Pointer to the offending value, which can help pinpoint where in a large document a runtime error occurred. This only applies to exceptions thrown *after* a value exists (e.g. during element access); parse errors, which happen before any value exists to point at, are not -covered by this mechanism -- see [Parsing and exceptions](../features/parsing/parse_exceptions.md) for how parse +covered by this mechanism — see [Parsing and exceptions](../features/parsing/parse_exceptions.md) for how parse errors report their own location instead. ## See also diff --git a/docs/mkdocs/docs/home/exceptions.md b/docs/mkdocs/docs/home/exceptions.md index baaea09cf..ab4787b73 100644 --- a/docs/mkdocs/docs/home/exceptions.md +++ b/docs/mkdocs/docs/home/exceptions.md @@ -230,7 +230,7 @@ JSON uses the `\uxxxx` format to describe Unicode characters. Code points above !!! failure "Example message" ``` - parse error at 14: missing or wrong low surrogate + [json.exception.parse_error.102] parse error at 14: missing or wrong low surrogate ``` !!! note @@ -244,7 +244,7 @@ Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are inva !!! failure "Example message" ``` - parse error: code points above 0x10FFFF are invalid + [json.exception.parse_error.103] parse error: code points above 0x10FFFF are invalid ``` !!! note @@ -940,7 +940,7 @@ The provided array index `i` is larger than `size-1`. !!! failure "Example message" ``` - array index 3 is out of range + [json.exception.out_of_range.401] array index 3 is out of range ``` ### json.exception.out_of_range.402 @@ -950,7 +950,7 @@ The special array index `-` in a JSON Pointer never describes a valid element of !!! failure "Example message" ``` - array index '-' (3) is out of range + [json.exception.out_of_range.402] array index '-' (3) is out of range ``` ### json.exception.out_of_range.403 @@ -960,7 +960,7 @@ The provided key was not found in the JSON object. !!! failure "Example message" ``` - key 'foo' not found + [json.exception.out_of_range.403] key 'foo' not found ``` ### json.exception.out_of_range.404 @@ -971,7 +971,7 @@ contains other characters (e.g., `1a`), or `-` where it cannot be used. !!! failure "Example message" ``` - unresolved reference token 'foo' + [json.exception.out_of_range.404] unresolved reference token 'foo' ``` ### json.exception.out_of_range.405 @@ -983,7 +983,7 @@ also thrown when the parent or a reference token of an empty JSON Pointer is req !!! failure "Example message" ``` - JSON pointer has no parent + [json.exception.out_of_range.405] JSON pointer has no parent ``` ### json.exception.out_of_range.406 @@ -995,7 +995,7 @@ double-precision number when `number_float_t` is `#!cpp float`. !!! failure "Example messages" ``` - number overflow parsing '10E1000' + [json.exception.out_of_range.406] number overflow parsing '10E1000' ``` ``` [json.exception.out_of_range.406] syntax error while parsing CBOR value: number overflow @@ -1030,10 +1030,10 @@ exception, because they serialize integers beyond 64 bits as high-precision numb !!! failure "Example messages" ``` - integer number 18446744073709551615 cannot be represented by BON8 as it does not fit int64 + [json.exception.out_of_range.407] integer number 18446744073709551615 cannot be represented by BON8 as it does not fit int64 ``` ``` - integer number 1267650600228229401496703205376 cannot be represented by CBOR as it does not fit [-2^64, 2^64-1] + [json.exception.out_of_range.407] integer number 1267650600228229401496703205376 cannot be represented by CBOR as it does not fit [-2^64, 2^64-1] ``` ### json.exception.out_of_range.408 @@ -1051,7 +1051,7 @@ so any value it produces can still be read back. !!! failure "Example messages" ``` - excessive array size: 8658170730974374167 + [json.exception.out_of_range.408] excessive array size: 8658170730974374167 ``` ``` [json.exception.out_of_range.408] syntax error while parsing CBOR size: excessive array size @@ -1070,7 +1070,7 @@ Key identifiers to be serialized to BSON cannot contain code point U+0000, since !!! failure "Example message" ``` - BSON key cannot contain code point U+0000 (at byte 2) + [json.exception.out_of_range.409] BSON key cannot contain code point U+0000 (at byte 2) ``` ### json.exception.out_of_range.410 @@ -1082,8 +1082,8 @@ a JSON pointer exceeds the range of `size_type` (e.g., on 32-bit platforms). !!! failure "Example message" ``` - enum value out of range - array index 18446744073709551615 exceeds size_type + [json.exception.out_of_range.410] enum value out of range + [json.exception.out_of_range.410] array index 18446744073709551615 exceeds size_type ``` The second message is thrown, for instance, by `#!cpp json::parse("[1, 2]").at("/18446744073709551615"_json_pointer)` @@ -1098,7 +1098,7 @@ A JSON Patch `add` operation cannot be applied because the target location's par !!! failure "Example message" ``` - cannot add value: the JSON Patch 'add' target's parent is of type string, but must be an object or array + [json.exception.out_of_range.411] cannot add value: the JSON Patch 'add' target's parent is of type string, but must be an object or array ``` !!! note @@ -1116,10 +1116,10 @@ is thrown when a value is too large to be described by such a length field. !!! failure "Example messages" ``` - BSON length 2147483661 exceeds maximum of 2147483647 + [json.exception.out_of_range.412] BSON length 2147483661 exceeds maximum of 2147483647 ``` ``` - MessagePack length 4294967296 exceeds maximum of 4294967295 + [json.exception.out_of_range.412] MessagePack length 4294967296 exceeds maximum of 4294967295 ``` !!! note @@ -1136,7 +1136,7 @@ A JSON Patch `remove` operation cannot be applied because the target location's !!! failure "Example message" ``` - cannot remove value: the JSON Patch 'remove' target's parent is of type number, but must be an object or array + [json.exception.out_of_range.413] cannot remove value: the JSON Patch 'remove' target's parent is of type number, but must be an object or array ``` !!! note @@ -1150,7 +1150,7 @@ A JSON Patch `move` operation's `"from"` location is a proper prefix of its `"pa !!! failure "Example message" ``` - cannot move value: 'from' path '/0' is a proper prefix of 'path' '/0/0' + [json.exception.out_of_range.414] cannot move value: 'from' path '/0' is a proper prefix of 'path' '/0/0' ``` !!! note diff --git a/docs/mkdocs/docs/home/faq.md b/docs/mkdocs/docs/home/faq.md index fc9638afc..c43acef37 100644 --- a/docs/mkdocs/docs/home/faq.md +++ b/docs/mkdocs/docs/home/faq.md @@ -20,7 +20,7 @@ yield different results (`#!json [true]` vs. `#!json true`)? -This is a known issue, and -- even worse -- the behavior differs between GCC and Clang. The "culprit" for this is the library's constructor overloads for initializer lists to allow syntax like +This is a known issue, and — even worse — the behavior differs between GCC and Clang. The "culprit" for this is the library's constructor overloads for initializer lists to allow syntax like ```cpp json array = {1, 2, 3, 4}; @@ -394,8 +394,8 @@ As described [above](#parse-errors-reading-non-ascii-characters), the library st No. `basic_json` provides no built-in synchronization, the same as `std::map` or `std::vector`. Concurrent reads of the same value from multiple threads are safe, as are concurrent (non-overlapping) accesses to independent `json` -objects. However, any concurrent write to a `json` object -- or a concurrent read while another thread writes to the -same object -- is a data race and requires external synchronization (e.g., a `std::mutex`) by the caller. +objects. However, any concurrent write to a `json` object — or a concurrent read while another thread writes to the +same object — is a data race and requires external synchronization (e.g., a `std::mutex`) by the caller. ### Schema validation diff --git a/docs/mkdocs/docs/home/releases/index.md b/docs/mkdocs/docs/home/releases/index.md index 6fe1eafdf..83ab024e1 100644 --- a/docs/mkdocs/docs/home/releases/index.md +++ b/docs/mkdocs/docs/home/releases/index.md @@ -20,7 +20,7 @@ All releases at a glance (hover a marker for its version and date): --8<-- "images/release_timeline.svg"
-

Releases from 1.0.0 to the latest one, on a time axis by year. Filled dots with a version label are minor or major releases, rings are patch releases.

+

From the first commit (diamond) in 2013 to the latest release, on a time axis by year. Filled dots with a version label are minor or major releases, rings are patch releases.

## Unreleased @@ -32,124 +32,124 @@ All releases at a glance (hover a marker for its version and date): | Release | Date | Summary | |---------|------|---------| -| [v3.12.0](v3.12.0.md) | 2025-04-11 | Fixes bugs found in 3.11.3 and adds several features. No public API was removed or renamed. | +| [v3.12.0](v3.12.0.md) | 2025-04-11 | Fixes bugs found in 3.11.3 and adds several features. No public API was removed or renamed. **Highlights:** diagnostic byte positions (`start_pos`/`end_pos`); templated conversion macros and `NLOHMANN_DEFINE_DERIVED_TYPE`; `std::optional` support. | ## Version 3.11.x | Release | Date | Summary | |---------|------|---------| -| [v3.11.3](v3.11.3.md) | 2023-11-28 | Adds features and fixes bugs found in 3.11.2. All changes are backward-compatible. | -| [v3.11.2](v3.11.2.md) | 2022-08-12 | Fixes bugs found in 3.11.1 and restructures the namespace. All changes are backward-compatible. | -| [v3.11.1](v3.11.1.md) | 2022-08-01 | Fixes a regression from 3.11.0. All changes are backward-compatible. | -| [v3.11.0](v3.11.0.md) | 2022-08-01 | One of the largest releases ever. All changes are backward-compatible. | +| [v3.11.3](v3.11.3.md) | 2023-11-28 | Adds features and fixes bugs found in 3.11.2. All changes are backward-compatible. **Highlights:** custom base class for `basic_json`; serialization-only conversion macros; Bazel and Swift Package Manager support. | +| [v3.11.2](v3.11.2.md) | 2022-08-12 | Fixes bugs found in 3.11.1 and restructures the namespace. All changes are backward-compatible. **Highlights:** fixes `value` for strings and size types; restores `json_pointer` as associative-container key; restructured inline namespace. | +| [v3.11.1](v3.11.1.md) | 2022-08-01 | Fixes a regression from 3.11.0. All changes are backward-compatible. **Highlights:** restores the global `_json` and `_json_pointer` literals. | +| [v3.11.0](v3.11.0.md) | 2022-08-01 | One of the largest releases ever. All changes are backward-compatible. **Highlights:** `std::string_view` keys; BJData binary format; C++20 support including `operator<=>`. | ## Version 3.10.x | Release | Date | Summary | |---------|------|---------| -| [v3.10.5](v3.10.5.md) | 2022-01-03 | Bug-fix release. All changes are backward-compatible. | -| [v3.10.4](v3.10.4.md) | 2021-10-16 | Fixes regressions introduced in 3.10.0. All changes are backward-compatible. | -| [v3.10.3](v3.10.3.md) | 2021-10-08 | Fixes more regressions from 3.10.0. All changes are backward-compatible. | -| [v3.10.2](v3.10.2.md) | 2021-08-26 | Re-release of 3.10.1, whose Git tag pointed at the wrong commit due to a bug in the release script. All changes are backward-compatible. | -| [v3.10.1](v3.10.1.md) | 2021-08-24 | Fixes a regression from 3.10.0. All changes are backward-compatible. | -| [v3.10.0](v3.10.0.md) | 2021-08-17 | Feature release. All changes are backward-compatible. | +| [v3.10.5](v3.10.5.md) | 2022-01-03 | Bug-fix release. All changes are backward-compatible. **Highlights:** guards the `std::filesystem` conversions with `JSON_HAS_FILESYSTEM`. | +| [v3.10.4](v3.10.4.md) | 2021-10-16 | Fixes regressions introduced in 3.10.0. All changes are backward-compatible. **Highlights:** fixes the `std::filesystem::path` conversion; fixes types with explicit defaulted constructors; fixes `std::find`/`std::remove` return values. | +| [v3.10.3](v3.10.3.md) | 2021-10-08 | Fixes more regressions from 3.10.0. All changes are backward-compatible. **Highlights:** fixes extended-diagnostics assertions in `update` and array insertion; custom allocators for binary output; conversion from `begin()`/`end()`-only types. | +| [v3.10.2](v3.10.2.md) | 2021-08-26 | Re-release of 3.10.1, whose Git tag pointed at the wrong commit due to a bug in the release script. All changes are backward-compatible. **Highlights:** re-release of 3.10.1 with the correct Git tag. | +| [v3.10.1](v3.10.1.md) | 2021-08-24 | Fixes a regression from 3.10.0. All changes are backward-compatible. **Highlights:** fixes an extended-diagnostics assertion with `ordered_json`; hardens the GDB pretty-printer. | +| [v3.10.0](v3.10.0.md) | 2021-08-17 | Feature release. All changes are backward-compatible. **Highlights:** extended diagnostic messages (`JSON_DIAGNOSTICS`); GDB pretty-printer; CBOR tag storage. | ## Version 3.9.x | Release | Date | Summary | |---------|------|---------| -| [v3.9.1](v3.9.1.md) | 2020-08-06 | Fixes two regressions from 3.9.0. All changes are backward-compatible. | -| [v3.9.0](v3.9.0.md) | 2020-07-27 | Feature release adding four long-requested features. All changes are backward-compatible. | +| [v3.9.1](v3.9.1.md) | 2020-08-06 | Fixes two regressions from 3.9.0. All changes are backward-compatible. **Highlights:** accepts consecutive comments; completes the `ordered_json` interface. | +| [v3.9.0](v3.9.0.md) | 2020-07-27 | Feature release adding four long-requested features. All changes are backward-compatible. **Highlights:** comment parsing; `ordered_json`; switch to disable implicit conversions. | ## Version 3.8.x | Release | Date | Summary | |---------|------|---------| -| [v3.8.0](v3.8.0.md) | 2020-06-14 | Feature release. All changes are backward-compatible. | +| [v3.8.0](v3.8.0.md) | 2020-06-14 | Feature release. All changes are backward-compatible. **Highlights:** binary value type for CBOR, BSON, and MessagePack; input adapters for any `LegacyInputIterator` container; fixes `contains` for JSON pointers. | ## Version 3.7.x | Release | Date | Summary | |---------|------|---------| -| [v3.7.3](v3.7.3.md) | 2019-11-17 | Fixes a regression from 3.7.2 that could yield quadratic complexity in destructor calls. All changes are backward-compatible. | -| [v3.7.2](v3.7.2.md) | 2019-11-10 | Fixes a stack overflow for deeply nested input by making the destructor iterative; parsing of JSON text is now bounded only by available memory (the binary-format parsers still recurse). All changes are backward-compatible. | -| [v3.7.1](v3.7.1.md) | 2019-11-06 | Bug-fix release. All changes are backward-compatible. | -| [v3.7.0](v3.7.0.md) | 2019-07-28 | Convenience features and house-keeping. All changes are backward-compatible. | +| [v3.7.3](v3.7.3.md) | 2019-11-17 | Fixes a regression from 3.7.2 that could yield quadratic complexity in destructor calls. All changes are backward-compatible. **Highlights:** fixes quadratic complexity in destructor calls. | +| [v3.7.2](v3.7.2.md) | 2019-11-10 | Fixes a stack overflow for deeply nested input by making the destructor iterative; parsing of JSON text is now bounded only by available memory (the binary-format parsers still recurse). All changes are backward-compatible. **Highlights:** iterative destructor fixes a stack overflow on deeply nested input. | +| [v3.7.1](v3.7.1.md) | 2019-11-06 | Bug-fix release. All changes are backward-compatible. **Highlights:** fixes a crash when serializing the minimum `std::int64_t`; fixes `contains` for JSON pointers; `items` with custom string types. | +| [v3.7.0](v3.7.0.md) | 2019-07-28 | Convenience features and house-keeping. All changes are backward-compatible. **Highlights:** `contains` overload for JSON pointers; generic `to_string`; return value for `emplace_back`. | ## Version 3.6.x | Release | Date | Summary | |---------|------|---------| -| [v3.6.1](v3.6.1.md) | 2019-03-20 | Fixes a regression (GCC 7/8 compilation) and a `` build error introduced in 3.6.0. All changes are backward-compatible. | -| [v3.6.0](v3.6.0.md) | 2019-03-20 | Feature release. All changes are backward-compatible. | +| [v3.6.1](v3.6.1.md) | 2019-03-20 | Fixes a regression (GCC 7/8 compilation) and a `` build error introduced in 3.6.0. All changes are backward-compatible. **Highlights:** fixes a GCC 7/8 compilation regression; fixes a `` build error. | +| [v3.6.0](v3.6.0.md) | 2019-03-20 | Feature release. All changes are backward-compatible. **Highlights:** reworked JSON pointer interface; `contains` function; faster integer serialization. | ## Version 3.5.x | Release | Date | Summary | |---------|------|---------| -| [v3.5.0](v3.5.0.md) | 2018-12-22 | Feature release. All changes are backward-compatible. | +| [v3.5.0](v3.5.0.md) | 2018-12-22 | Feature release. All changes are backward-compatible. **Highlights:** structured bindings via `items`; reading from `FILE*`; fixes `eofbit` handling on streams. | ## Version 3.4.x | Release | Date | Summary | |---------|------|---------| -| [v3.4.0](v3.4.0.md) | 2018-10-30 | Feature release. All changes are backward-compatible. | +| [v3.4.0](v3.4.0.md) | 2018-10-30 | Feature release. All changes are backward-compatible. **Highlights:** BSON support; Unicode error handlers for `dump`; `NLOHMANN_JSON_SERIALIZE_ENUM`. | ## Version 3.3.x | Release | Date | Summary | |---------|------|---------| -| [v3.3.0](v3.3.0.md) | 2018-10-05 | Feature release. All changes are backward-compatible. | +| [v3.3.0](v3.3.0.md) | 2018-10-05 | Feature release. All changes are backward-compatible. **Highlights:** GCC 4.8 support; `get_to`; overhauled CMake integration. | ## Version 3.2.x | Release | Date | Summary | |---------|------|---------| -| [v3.2.0](v3.2.0.md) | 2018-08-20 | Feature release. All changes are backward-compatible. | +| [v3.2.0](v3.2.0.md) | 2018-08-20 | Feature release. All changes are backward-compatible. **Highlights:** SAX interface and non-recursive parser; parsing from wide strings; conversion to `std::string_view`. | ## Version 3.1.x | Release | Date | Summary | |---------|------|---------| -| [v3.1.2](v3.1.2.md) | 2018-03-14 | Bug-fix release. All changes are backward-compatible. | -| [v3.1.1](v3.1.1.md) | 2018-02-13 | Bug-fix release. All changes are backward-compatible. | -| [v3.1.0](v3.1.0.md) | 2018-02-01 | Feature release. All changes are backward-compatible. | +| [v3.1.2](v3.1.2.md) | 2018-03-14 | Bug-fix release. All changes are backward-compatible. **Highlights:** fixes a memory leak in the parser callback; user-defined string types in parser and serializer. | +| [v3.1.1](v3.1.1.md) | 2018-02-13 | Bug-fix release. All changes are backward-compatible. **Highlights:** fixes parsing of indefinite-length CBOR strings; fixes a user-defined conversion to vector types; fixes UBJSON overflow detection. | +| [v3.1.0](v3.1.0.md) | 2018-02-01 | Feature release. All changes are backward-compatible. **Highlights:** UBJSON support; JSON Merge Patch; Grisu2 floating-point output. | ## Version 3.0.x | Release | Date | Summary | |---------|------|---------| -| [v3.0.1](v3.0.1.md) | 2017-12-29 | Fixes small issues in the [JSON Pointer](../../features/json_pointer.md) and [JSON Patch](../../features/json_patch.md) implementations (invalid "copy" targets and non-integer array indices). All changes are backward-compatible. | -| [v3.0.0](v3.0.0.md) | 2017-12-17 | First 3.x release — a major release with breaking changes (see the [migration guide](../../integration/migration_guide.md)). | +| [v3.0.1](v3.0.1.md) | 2017-12-29 | Fixes small issues in the [JSON Pointer](../../features/json_pointer.md) and [JSON Patch](../../features/json_patch.md) implementations (invalid "copy" targets and non-integer array indices). All changes are backward-compatible. **Highlights:** fixes invalid JSON Patch "copy" targets; fixes non-integer array indices in JSON Pointer. | +| [v3.0.0](v3.0.0.md) | 2017-12-17 | First 3.x release — a major release with breaking changes (see the [migration guide](../../integration/migration_guide.md)). **Highlights:** user-defined exceptions with identifiers; non-throwing `accept` and `allow_exceptions`; `update` to merge objects. | ## Version 2.1.x | Release | Date | Summary | |---------|------|---------| -| [v2.1.1](v2.1.1.md) | 2017-02-25 | Bug-fix release. All changes are backward-compatible. | -| [v2.1.0](v2.1.0.md) | 2017-01-28 | Feature release. All changes are backward-compatible. | +| [v2.1.1](v2.1.1.md) | 2017-02-25 | Bug-fix release. All changes are backward-compatible. **Highlights:** locale-independent number parsing and serialization; correct floating-point round-tripping; GPG-signed commits and files. | +| [v2.1.0](v2.1.0.md) | 2017-01-28 | Feature release. All changes are backward-compatible. **Highlights:** conversions from and to arbitrary user-defined types; `meta` function; `JSON_NOEXCEPTION`. | ## Version 2.0.x | Release | Date | Summary | |---------|------|---------| -| [v2.0.10](v2.0.10.md) | 2017-01-02 | Fixes several security-relevant bugs in the CBOR and MessagePack parsers found by OSS-Fuzz. All changes are backward-compatible. | -| [v2.0.9](v2.0.9.md) | 2016-12-16 | Adds the [CBOR](../../features/binary_formats/cbor.md) and [MessagePack](../../features/binary_formats/messagepack.md) binary formats. All changes are backward-compatible. | -| [v2.0.8](v2.0.8.md) | 2016-12-02 | Adds the [`emplace`](../../api/basic_json/emplace.md) and [`emplace_back`](../../api/basic_json/emplace_back.md) functions and improves parsing and serialization performance. All changes are backward-compatible. | -| [v2.0.7](v2.0.7.md) | 2016-11-02 | Fixes several parser bugs found through the "Parsing JSON is a Minefield" study (short files, encoding detection, surrogate pairs). All changes are backward-compatible. | -| [v2.0.6](v2.0.6.md) | 2016-10-15 | Fixes [`operator[]`](../../api/basic_json/operator%5B%5D.md) for [JSON pointers](../../features/json_pointer.md) so that it creates missing values like the other overloads. All changes are backward-compatible. | -| [v2.0.5](v2.0.5.md) | 2016-09-14 | Fixes a remaining stream end-of-file detection bug in the parser. All changes are backward-compatible. | -| [v2.0.4](v2.0.4.md) | 2016-09-11 | Fixes stream end-of-file detection in the parser. All changes are backward-compatible. | -| [v2.0.3](v2.0.3.md) | 2016-08-31 | Generalizes the parser to accept any contiguous sequence of one-byte elements and deprecates the input-stream constructor in favor of the [`parse`](../../api/basic_json/parse.md) function. All changes are backward-compatible. | -| [v2.0.2](v2.0.2.md) | 2016-07-31 | Overhauls the parser (now rejecting unescaped control characters), tightens the class invariants, and cleans up the code. All changes are backward-compatible. | -| [v2.0.1](v2.0.1.md) | 2016-06-28 | Fixes a performance regression in the [`dump`](../../api/basic_json/dump.md) function by adjusting the stream locale once per serialization. All changes are backward-compatible. | -| [v2.0.0](v2.0.0.md) | 2016-06-24 | Feature release with a minor (potentially non-backward-compatible) API change from added `noexcept` and `constexpr` specifiers. | +| [v2.0.10](v2.0.10.md) | 2017-01-02 | Fixes several security-relevant bugs in the CBOR and MessagePack parsers found by OSS-Fuzz. All changes are backward-compatible. **Highlights:** fixes security-relevant bugs in the CBOR parser; fixes security-relevant bugs in the MessagePack parser. | +| [v2.0.9](v2.0.9.md) | 2016-12-16 | Adds the [CBOR](../../features/binary_formats/cbor.md) and [MessagePack](../../features/binary_formats/messagepack.md) binary formats. All changes are backward-compatible. **Highlights:** CBOR support; MessagePack support. | +| [v2.0.8](v2.0.8.md) | 2016-12-02 | Adds the [`emplace`](../../api/basic_json/emplace.md) and [`emplace_back`](../../api/basic_json/emplace_back.md) functions and improves parsing and serialization performance. All changes are backward-compatible. **Highlights:** `emplace` and `emplace_back`; faster parsing; faster serialization. | +| [v2.0.7](v2.0.7.md) | 2016-11-02 | Fixes several parser bugs found through the "Parsing JSON is a Minefield" study (short files, encoding detection, surrogate pairs). All changes are backward-compatible. **Highlights:** fixes short-file handling; fixes encoding detection; fixes surrogate pairs. | +| [v2.0.6](v2.0.6.md) | 2016-10-15 | Fixes [`operator[]`](../../api/basic_json/operator%5B%5D.md) for [JSON pointers](../../features/json_pointer.md) so that it creates missing values like the other overloads. All changes are backward-compatible. **Highlights:** `operator[]` creates missing values for JSON pointers. | +| [v2.0.5](v2.0.5.md) | 2016-09-14 | Fixes a remaining stream end-of-file detection bug in the parser. All changes are backward-compatible. **Highlights:** fixes a remaining stream end-of-file bug. | +| [v2.0.4](v2.0.4.md) | 2016-09-11 | Fixes stream end-of-file detection in the parser. All changes are backward-compatible. **Highlights:** fixes stream end-of-file detection. | +| [v2.0.3](v2.0.3.md) | 2016-08-31 | Generalizes the parser to accept any contiguous sequence of one-byte elements and deprecates the input-stream constructor in favor of the [`parse`](../../api/basic_json/parse.md) function. All changes are backward-compatible. **Highlights:** parser accepts any contiguous sequence of one-byte elements; deprecates the input-stream constructor in favor of `parse`. | +| [v2.0.2](v2.0.2.md) | 2016-07-31 | Overhauls the parser (now rejecting unescaped control characters), tightens the class invariants, and cleans up the code. All changes are backward-compatible. **Highlights:** overhauled parser rejecting unescaped control characters; tighter class invariants; code cleanup. | +| [v2.0.1](v2.0.1.md) | 2016-06-28 | Fixes a performance regression in the [`dump`](../../api/basic_json/dump.md) function by adjusting the stream locale once per serialization. All changes are backward-compatible. **Highlights:** fixes a performance regression in `dump`. | +| [v2.0.0](v2.0.0.md) | 2016-06-24 | Feature release with a minor (potentially non-backward-compatible) API change from added `noexcept` and `constexpr` specifiers. **Highlights:** JSON Pointer support in `at` and `operator[]`, plus `flatten` and `unflatten`; JSON Patch via `diff` and `patch`; unsigned 64-bit integers. | ## Version 1.1.x | Release | Date | Summary | |---------|------|---------| -| [v1.1.0](v1.1.0.md) | 2016-01-24 | Bug-fix and feature release. All changes are backward-compatible. | +| [v1.1.0](v1.1.0.md) | 2016-01-24 | Bug-fix and feature release. All changes are backward-compatible. **Highlights:** improved floating-point round-tripping; `get_ref`; runtime assertions. | ## Version 1.0.x @@ -161,3 +161,5 @@ All releases at a glance (hover a marker for its version and date): - [Migration Guide](../../integration/migration_guide.md) — how to future-proof your code for the next major version and replace deprecated functions. +- [Roadmap: Version 4.0](../../community/roadmap.md#version-40) — what the next major version will change and how to + try it today. diff --git a/docs/mkdocs/docs/home/sponsors.md b/docs/mkdocs/docs/home/sponsors.md index ddbfbf3f0..c42b6ce5b 100644 --- a/docs/mkdocs/docs/home/sponsors.md +++ b/docs/mkdocs/docs/home/sponsors.md @@ -1,18 +1,31 @@ # Sponsors -You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). +You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). Thanks to everyone who +supports the project! -## Priority Sponsor +## Priority Sponsors -- [Martti Laine](https://github.com/codeclown) -- [Paul Harrington](https://github.com/phrrngtn) +- [Mercedes-Benz](https://github.com/mercedes-benz) +- [FastNetMon](https://github.com/FastNetMon) ## Named Sponsors +- [Paul Harrington](https://github.com/phrrngtn) +- [Steve Wagner](https://github.com/ciroque) +- [mccaffers](https://github.com/mccaffers) +- [jambolo](https://github.com/jambolo) + +## Further Sponsors + +- [Grisha Kirilin](https://github.com/GrishaKirilin) +- [zimmerman-dev](https://github.com/zimmerman-dev) +- [WAAutoMaton](https://github.com/WAAutoMaton) +- [F3D](https://github.com/f3d-app) +- [David Alvarez Rosa](https://github.com/david-alvarez-rosa) +- [Alex Kong](https://github.com/alex-lt-kong) +- [Mark Oates](https://github.com/MarkOates) +- [Martti Laine](https://github.com/codeclown) - Michael Hartmann - [Stefan Hagen](https://github.com/sthagen) - [Steve Sperandeo](https://github.com/homer6) - [Robert Jefe Lindstädt](https://github.com/eljefedelrodeodeljefe) -- [Steve Wagner](https://github.com/ciroque) - -Thanks everyone! diff --git a/docs/mkdocs/docs/images/release_timeline.svg b/docs/mkdocs/docs/images/release_timeline.svg index 98a19f332..b70e92218 100644 --- a/docs/mkdocs/docs/images/release_timeline.svg +++ b/docs/mkdocs/docs/images/release_timeline.svg @@ -1,109 +1,116 @@ - -Timeline of the 44 releases from v1.0.0 (2015-12-28) to v3.12.0 (2025-04-11): 17 minor or major releases, drawn as filled dots with their version above the axis, and 27 patch releases, drawn as rings. - -2015 - -2016 - -2017 - -2018 - -2019 - -2020 - -2021 - -2022 - -2023 - -2024 - -2025 - - - -1.x - -2.x - -3.x - -1.0 - -1.1 - -2.0 - -2.1 - -3.0 - -3.1 - -3.2 - -3.3 - -3.4 - -3.5 - -3.6 - -3.7 - -3.8 - -3.9 - -3.10 - -3.11 - -3.12 -v2.0.1 released 2016-06-28 -v2.0.2 released 2016-07-31 -v2.0.3 released 2016-08-31 -v2.0.4 released 2016-09-11 -v2.0.5 released 2016-09-14 -v2.0.6 released 2016-10-15 -v2.0.7 released 2016-11-02 -v2.0.8 released 2016-12-02 -v2.0.9 released 2016-12-16 -v2.0.10 released 2017-01-02 -v2.1.1 released 2017-02-25 -v3.0.1 released 2017-12-29 -v3.1.1 released 2018-02-13 -v3.1.2 released 2018-03-14 -v3.7.1 released 2019-11-06 -v3.7.2 released 2019-11-10 -v3.7.3 released 2019-11-17 -v3.9.1 released 2020-08-06 -v3.10.1 released 2021-08-24 -v3.10.2 released 2021-08-26 -v3.10.3 released 2021-10-08 -v3.10.4 released 2021-10-16 -v3.10.5 released 2022-01-03 -v3.11.2 released 2022-08-12 -v3.11.3 released 2023-11-28 -v1.0.0 released 2015-12-28 -v1.1.0 released 2016-01-24 -v2.0.0 released 2016-06-24 -v2.1.0 released 2017-01-28 -v3.0.0 released 2017-12-17 -v3.1.0 released 2018-02-01 -v3.2.0 released 2018-08-20 -v3.3.0 released 2018-10-05 -v3.4.0 released 2018-10-30 -v3.5.0 released 2018-12-22 -v3.6.0, v3.6.1 released 2019-03-20 -v3.7.0 released 2019-07-28 -v3.8.0 released 2020-06-14 -v3.9.0 released 2020-07-27 -v3.10.0 released 2021-08-17 -v3.11.0, v3.11.1 released 2022-08-01 -v3.12.0 released 2025-04-11 + +Timeline from the first commit (2013-07-04) and the 44 releases from v1.0.0 (2015-12-28) to v3.12.0 (2025-04-11): 17 minor or major releases, drawn as filled dots with their version above the axis, and 27 patch releases, drawn as rings. The first commit is drawn as a diamond. + +2013 + +2014 + +2015 + +2016 + +2017 + +2018 + +2019 + +2020 + +2021 + +2022 + +2023 + +2024 + +2025 + + + +1.x + +2.x + +3.x + +first commit + +1.0 + +1.1 + +2.0 + +2.1 + +3.0 + +3.1 + +3.2 + +3.3 + +3.4 + +3.5 + +3.6 + +3.7 + +3.8 + +3.9 + +3.10 + +3.11 + +3.12 +First commit 2013-07-04 +v2.0.1 released 2016-06-28 +v2.0.2 released 2016-07-31 +v2.0.3 released 2016-08-31 +v2.0.4 released 2016-09-11 +v2.0.5 released 2016-09-14 +v2.0.6 released 2016-10-15 +v2.0.7 released 2016-11-02 +v2.0.8 released 2016-12-02 +v2.0.9 released 2016-12-16 +v2.0.10 released 2017-01-02 +v2.1.1 released 2017-02-25 +v3.0.1 released 2017-12-29 +v3.1.1 released 2018-02-13 +v3.1.2 released 2018-03-14 +v3.7.1 released 2019-11-06 +v3.7.2 released 2019-11-10 +v3.7.3 released 2019-11-17 +v3.9.1 released 2020-08-06 +v3.10.1 released 2021-08-24 +v3.10.2 released 2021-08-26 +v3.10.3 released 2021-10-08 +v3.10.4 released 2021-10-16 +v3.10.5 released 2022-01-03 +v3.11.2 released 2022-08-12 +v3.11.3 released 2023-11-28 +v1.0.0 released 2015-12-28 +v1.1.0 released 2016-01-24 +v2.0.0 released 2016-06-24 +v2.1.0 released 2017-01-28 +v3.0.0 released 2017-12-17 +v3.1.0 released 2018-02-01 +v3.2.0 released 2018-08-20 +v3.3.0 released 2018-10-05 +v3.4.0 released 2018-10-30 +v3.5.0 released 2018-12-22 +v3.6.0, v3.6.1 released 2019-03-20 +v3.7.0 released 2019-07-28 +v3.8.0 released 2020-06-14 +v3.9.0 released 2020-07-27 +v3.10.0 released 2021-08-17 +v3.11.0, v3.11.1 released 2022-08-01 +v3.12.0 released 2025-04-11 diff --git a/docs/mkdocs/docs/index.md b/docs/mkdocs/docs/index.md index 51d3c97a6..b18e1de1c 100644 --- a/docs/mkdocs/docs/index.md +++ b/docs/mkdocs/docs/index.md @@ -12,8 +12,8 @@ hide: --- - Creating, parsing, accessing, and serializing JSON values, JSON Pointer/Patch, binary formats, zero-copy views, - and more. + Creating, parsing, accessing, and serializing JSON values, converting your own C++ types, JSON Pointer/Patch/Merge + Patch, binary formats, zero-copy views, and more. [:octicons-arrow-right-24: Features](features/index.md) diff --git a/docs/mkdocs/docs/js/external-links.js b/docs/mkdocs/docs/js/external-links.js new file mode 100644 index 000000000..bdafe4c2a --- /dev/null +++ b/docs/mkdocs/docs/js/external-links.js @@ -0,0 +1,32 @@ +/* + * Marks links that leave the site with the class "nj-external", which brand.css turns into a small icon in front of + * the link. A link is external when its host is neither the current one nor the production site. Links in the page + * actions (edit, raw), buttons, header anchors, and links that only wrap an image (badges) are left alone. + * Runs through Material's document$ (navigation.instant), so it also applies after an instant page switch. + */ +(function () { + "use strict"; + + function mark() { + var links = document.querySelectorAll(".md-typeset a[href]"); + for (var i = 0; i < links.length; i++) { + var a = links[i]; + if (a.hostname === "" || a.hostname === location.hostname || a.hostname === "json.nlohmann.me") { + continue; + } + if (a.protocol !== "http:" && a.protocol !== "https:") { + continue; + } + if (a.matches(".md-button, .md-content__button, .headerlink") || a.querySelector("img, svg")) { + continue; + } + a.classList.add("nj-external"); + } + } + + if (window.document$ && window.document$.subscribe) { + window.document$.subscribe(mark); + } else { + document.addEventListener("DOMContentLoaded", mark); + } +})(); diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index a0779b0a7..d2ec8f7df 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -642,6 +642,7 @@ extra_css: extra_javascript: - js/mermaid-brand.js + - js/external-links.js - js/fig-sax.js - js/fig-jsonview.js - js/fig-exceptions.js diff --git a/docs/mkdocs/overrides/home.html b/docs/mkdocs/overrides/home.html index 5fb50dfbc..6ff5e09a8 100644 --- a/docs/mkdocs/overrides/home.html +++ b/docs/mkdocs/overrides/home.html @@ -11,6 +11,7 @@

Get started API documentation + Latest release