From c034480c22eeb0d95f79e2db1c4f992c9c5faa8e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 4 Jul 2026 11:13:25 +0200 Subject: [PATCH] :memo: add more docs (#5231) Signed-off-by: Niels Lohmann --- docs/mkdocs/docs/api/basic_json/array.md | 1 + docs/mkdocs/docs/api/basic_json/dump.md | 1 + docs/mkdocs/docs/api/basic_json/emplace.md | 1 + .../docs/api/basic_json/emplace_back.md | 1 + docs/mkdocs/docs/api/basic_json/erase.md | 1 + docs/mkdocs/docs/api/basic_json/format_as.md | 1 + docs/mkdocs/docs/api/basic_json/get.md | 1 + docs/mkdocs/docs/api/basic_json/get_to.md | 1 + docs/mkdocs/docs/api/basic_json/object.md | 1 + .../docs/api/basic_json/operator_ValueType.md | 1 + docs/mkdocs/docs/api/basic_json/push_back.md | 1 + .../docs/api/basic_json/std_formatter.md | 1 + docs/mkdocs/docs/api/basic_json/to_string.md | 1 + docs/mkdocs/docs/api/basic_json/update.md | 1 + docs/mkdocs/docs/api/operator_literal_json.md | 4 + docs/mkdocs/docs/api/operator_ltlt.md | 6 + docs/mkdocs/docs/features/arbitrary_types.md | 4 +- docs/mkdocs/docs/features/assertions.md | 2 +- .../docs/features/binary_formats/bjdata.md | 4 +- .../docs/features/binary_formats/bson.md | 45 +++--- .../docs/features/binary_formats/cbor.md | 10 +- .../docs/features/binary_formats/index.md | 2 +- docs/mkdocs/docs/features/binary_values.md | 18 +-- docs/mkdocs/docs/features/conversions.md | 91 ++++++++++++ docs/mkdocs/docs/features/creating_values.md | 103 ++++++++++++++ .../features/element_access/checked_access.md | 4 +- .../features/element_access/default_value.md | 2 +- docs/mkdocs/docs/features/index.md | 53 +++++++ docs/mkdocs/docs/features/iterators.md | 2 +- docs/mkdocs/docs/features/json_patch.md | 2 +- docs/mkdocs/docs/features/modifying_values.md | 77 +++++++++++ docs/mkdocs/docs/features/namespace.md | 3 +- docs/mkdocs/docs/features/object_order.md | 6 +- docs/mkdocs/docs/features/parsing/index.md | 56 +++++++- docs/mkdocs/docs/features/serialization.md | 129 ++++++++++++++++++ docs/mkdocs/docs/features/types/index.md | 2 +- .../docs/features/types/number_handling.md | 12 +- docs/mkdocs/mkdocs.yml | 11 +- 38 files changed, 597 insertions(+), 65 deletions(-) create mode 100644 docs/mkdocs/docs/features/conversions.md create mode 100644 docs/mkdocs/docs/features/creating_values.md create mode 100644 docs/mkdocs/docs/features/index.md create mode 100644 docs/mkdocs/docs/features/modifying_values.md create mode 100644 docs/mkdocs/docs/features/serialization.md diff --git a/docs/mkdocs/docs/api/basic_json/array.md b/docs/mkdocs/docs/api/basic_json/array.md index 22b2ee1db..cbc5a723e 100644 --- a/docs/mkdocs/docs/api/basic_json/array.md +++ b/docs/mkdocs/docs/api/basic_json/array.md @@ -54,6 +54,7 @@ This function is only needed to express two edge cases that cannot be realized w - [`basic_json(initializer_list_t)`](basic_json.md) - create a JSON value from an initializer list - [`object`](object.md) - create a JSON object value from an initializer list +- [Creating JSON values](../../features/creating_values.md) - the article on creating JSON values ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/dump.md b/docs/mkdocs/docs/api/basic_json/dump.md index 1334d8eee..3e50daa1c 100644 --- a/docs/mkdocs/docs/api/basic_json/dump.md +++ b/docs/mkdocs/docs/api/basic_json/dump.md @@ -75,6 +75,7 @@ Binary values are serialized as an object containing two keys: - [to_string](to_string.md) returns a string representation of a JSON value - [operator<<](../operator_ltlt.md) serialize to stream +- [Serialization](../../features/serialization.md) - the serialization article ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/emplace.md b/docs/mkdocs/docs/api/basic_json/emplace.md index ffcb80184..18286e83f 100644 --- a/docs/mkdocs/docs/api/basic_json/emplace.md +++ b/docs/mkdocs/docs/api/basic_json/emplace.md @@ -64,6 +64,7 @@ Logarithmic in the size of the container, O(log(`size()`)). - [emplace_back](emplace_back.md) add a value to an array - [insert](insert.md) add values to an array/object +- [Modifying values](../../features/modifying_values.md) - the article on modifying values ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/emplace_back.md b/docs/mkdocs/docs/api/basic_json/emplace_back.md index 21829c216..516a66e5d 100644 --- a/docs/mkdocs/docs/api/basic_json/emplace_back.md +++ b/docs/mkdocs/docs/api/basic_json/emplace_back.md @@ -58,6 +58,7 @@ Amortized constant. - [operator+=](operator+=.md) add a value to an array/object - [push_back](push_back.md) add a value to an array/object +- [Modifying values](../../features/modifying_values.md) - the article on modifying values ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/erase.md b/docs/mkdocs/docs/api/basic_json/erase.md index 68f48e26c..d1e6d6d22 100644 --- a/docs/mkdocs/docs/api/basic_json/erase.md +++ b/docs/mkdocs/docs/api/basic_json/erase.md @@ -206,6 +206,7 @@ Strong exception safety: if an exception occurs, the original value stays intact - [clear](clear.md) clears the contents - [insert](insert.md) add values to an array/object +- [Modifying values](../../features/modifying_values.md) - the article on modifying values ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/format_as.md b/docs/mkdocs/docs/api/basic_json/format_as.md index d4315ce44..b35d0ddcd 100644 --- a/docs/mkdocs/docs/api/basic_json/format_as.md +++ b/docs/mkdocs/docs/api/basic_json/format_as.md @@ -88,6 +88,7 @@ std::string format_as(const BasicJsonType& j) - [dump](dump.md) - [std::formatter](std_formatter.md) - the `std::format` (C++20) equivalent +- [Serialization](../../features/serialization.md) - the serialization article ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/get.md b/docs/mkdocs/docs/api/basic_json/get.md index 9b78d3dd0..adf63b8a7 100644 --- a/docs/mkdocs/docs/api/basic_json/get.md +++ b/docs/mkdocs/docs/api/basic_json/get.md @@ -155,6 +155,7 @@ overload (3). - [get_ptr](get_ptr.md) get a pointer to the stored value - [get_ref](get_ref.md) get a reference to the stored value - [operator ValueType](operator_ValueType.md) get a value via implicit conversion +- [Converting values](../../features/conversions.md) - the type conversions article ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/get_to.md b/docs/mkdocs/docs/api/basic_json/get_to.md index 3c3764aec..8334ba5cf 100644 --- a/docs/mkdocs/docs/api/basic_json/get_to.md +++ b/docs/mkdocs/docs/api/basic_json/get_to.md @@ -62,6 +62,7 @@ Depends on the `json_serializer::from_json()` implementation. - [get](get.md) get a value (explicit conversion) - [get_ref](get_ref.md) get a reference to the stored value - [get_ptr](get_ptr.md) get a pointer to the stored value +- [Converting values](../../features/conversions.md) - the type conversions article ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/object.md b/docs/mkdocs/docs/api/basic_json/object.md index 73fbcaf79..53d969e56 100644 --- a/docs/mkdocs/docs/api/basic_json/object.md +++ b/docs/mkdocs/docs/api/basic_json/object.md @@ -57,6 +57,7 @@ the initializer list constructor `basic_json(initializer_list_t, bool, value_t)` - [`basic_json(initializer_list_t)`](basic_json.md) - create a JSON value from an initializer list - [`array`](array.md) - create a JSON array value from an initializer list +- [Creating JSON values](../../features/creating_values.md) - the article on creating JSON values ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/operator_ValueType.md b/docs/mkdocs/docs/api/basic_json/operator_ValueType.md index 110509b1c..231a33df4 100644 --- a/docs/mkdocs/docs/api/basic_json/operator_ValueType.md +++ b/docs/mkdocs/docs/api/basic_json/operator_ValueType.md @@ -78,6 +78,7 @@ Linear in the size of the JSON value. ## See also - [get](get.md) get a value (explicit conversion) +- [Converting values](../../features/conversions.md) - the type conversions article ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/push_back.md b/docs/mkdocs/docs/api/basic_json/push_back.md index 8a0fc9d9d..9d518e79e 100644 --- a/docs/mkdocs/docs/api/basic_json/push_back.md +++ b/docs/mkdocs/docs/api/basic_json/push_back.md @@ -115,6 +115,7 @@ invalidates all iterators and all references. - [emplace_back](emplace_back.md) add a value to an array - [operator+=](operator+=.md) add a value to an array/object +- [Modifying values](../../features/modifying_values.md) - the article on modifying values ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/std_formatter.md b/docs/mkdocs/docs/api/basic_json/std_formatter.md index dee77ef6c..be1d2d22e 100644 --- a/docs/mkdocs/docs/api/basic_json/std_formatter.md +++ b/docs/mkdocs/docs/api/basic_json/std_formatter.md @@ -50,6 +50,7 @@ provides ``, controlled by the [`JSON_HAS_STD_FORMAT`](../macros/json_ha - [dump](dump.md) - serialization - [operator<<(std::ostream&)](../operator_ltlt.md) - serialize to stream - [format_as](format_as.md) - customization point used by `fmt::format` (fmtlib) +- [Serialization](../../features/serialization.md) - the serialization article ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/to_string.md b/docs/mkdocs/docs/api/basic_json/to_string.md index 2b907e217..2df16c132 100644 --- a/docs/mkdocs/docs/api/basic_json/to_string.md +++ b/docs/mkdocs/docs/api/basic_json/to_string.md @@ -59,6 +59,7 @@ std::string to_string(const BasicJsonType& j) ## See also - [dump](dump.md) +- [Serialization](../../features/serialization.md) - the serialization article ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/update.md b/docs/mkdocs/docs/api/basic_json/update.md index a9729d98f..b34140dbc 100644 --- a/docs/mkdocs/docs/api/basic_json/update.md +++ b/docs/mkdocs/docs/api/basic_json/update.md @@ -149,6 +149,7 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value - [insert](insert.md) add values to an array/object - [merge_patch](merge_patch.md) applies a JSON Merge Patch +- [Modifying values](../../features/modifying_values.md) - the article on modifying values ## Version history diff --git a/docs/mkdocs/docs/api/operator_literal_json.md b/docs/mkdocs/docs/api/operator_literal_json.md index 1ea2db568..74cc9450c 100644 --- a/docs/mkdocs/docs/api/operator_literal_json.md +++ b/docs/mkdocs/docs/api/operator_literal_json.md @@ -56,6 +56,10 @@ Linear. --8<-- "examples/operator_literal_json.output" ``` +## See also + +- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values + ## Version history - Added in version 1.0.0. diff --git a/docs/mkdocs/docs/api/operator_ltlt.md b/docs/mkdocs/docs/api/operator_ltlt.md index 8dedb0509..1f99493d9 100644 --- a/docs/mkdocs/docs/api/operator_ltlt.md +++ b/docs/mkdocs/docs/api/operator_ltlt.md @@ -80,6 +80,12 @@ Linear. ```json --8<-- "examples/operator_ltlt__json_pointer.output" ``` + +## See also + +- [dump](basic_json/dump.md) - serialize to a JSON-formatted string +- [Serialization](../features/serialization.md) - the serialization article + ## Version history 1. Added in version 1.0.0. Added support for indentation character and deprecated diff --git a/docs/mkdocs/docs/features/arbitrary_types.md b/docs/mkdocs/docs/features/arbitrary_types.md index 1efb4be15..949037fd1 100644 --- a/docs/mkdocs/docs/features/arbitrary_types.md +++ b/docs/mkdocs/docs/features/arbitrary_types.md @@ -85,7 +85,7 @@ Some important things: If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate. -There are several macros to make your life easier as long as you want to use a JSON object as serialization. The macros are following the naming pattern, and you can chose the macro based on the needed features: +There are several macros to make your life easier as long as you want to use a JSON object as serialization. The macros are following the naming pattern, and you can choose the macro based on the needed features: - All the macros start with `NLOHMANN_DEFINE`. - If you want a macro for the derived object, use the [`DERIVED_TYPE`](../api/macros/nlohmann_define_derived_type.md) variant, otherwise use `TYPE`. @@ -139,7 +139,7 @@ For _derived_ classes and structs, use the following macros ```cpp namespace ns { struct person_derived : person { - std:string email; + std::string email; }; NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(person_derived, person, email) diff --git a/docs/mkdocs/docs/features/assertions.md b/docs/mkdocs/docs/features/assertions.md index 4d75d5a8a..789af7989 100644 --- a/docs/mkdocs/docs/features/assertions.md +++ b/docs/mkdocs/docs/features/assertions.md @@ -11,7 +11,7 @@ Runtime assertions can be switched off by defining the preprocessor macro `NDEBU ## Change assertion behavior -The behavior of runtime assertions can be changes by defining macro [`JSON_ASSERT(x)`](../api/macros/json_assert.md) +The behavior of runtime assertions can be changed by defining macro [`JSON_ASSERT(x)`](../api/macros/json_assert.md) before including the `json.hpp` header. ## Function with runtime assertions diff --git a/docs/mkdocs/docs/features/binary_formats/bjdata.md b/docs/mkdocs/docs/features/binary_formats/bjdata.md index a7631baee..b1b98dfe2 100644 --- a/docs/mkdocs/docs/features/binary_formats/bjdata.md +++ b/docs/mkdocs/docs/features/binary_formats/bjdata.md @@ -123,7 +123,7 @@ The library uses the following mapping from JSON values types to BJData types ac The current version of this library does not yet support automatic detection of and conversion from a nested JSON array input to a BJData ND-array. - [JDataAAFmt]: https://github.com/NeuroJSON/jdata/blob/master/JData_specification.md#annotated-storage-of-n-d-arrays) + [JDataAAFmt]: https://github.com/NeuroJSON/jdata/blob/master/JData_specification.md#annotated-storage-of-n-d-arrays !!! info "Restrictions in optimized data types for arrays and objects" @@ -146,7 +146,7 @@ The library uses the following mapping from JSON values types to BJData types ac suggested by the BJData documentation. In particular, this means that the serialization and the deserialization of JSON containing binary values into BJData and back will result in a different JSON object. - [BJDataBinArr]: https://github.com/NeuroJSON/bjdata/blob/master/Binary_JData_Specification.md#optimized-binary-array) + [BJDataBinArr]: https://github.com/NeuroJSON/bjdata/blob/master/Binary_JData_Specification.md#optimized-binary-array ??? example diff --git a/docs/mkdocs/docs/features/binary_formats/bson.md b/docs/mkdocs/docs/features/binary_formats/bson.md index cf87731a0..9b7685131 100644 --- a/docs/mkdocs/docs/features/binary_formats/bson.md +++ b/docs/mkdocs/docs/features/binary_formats/bson.md @@ -52,28 +52,29 @@ The library uses the following mapping from JSON values types to BSON types: The library maps BSON record types to JSON value types as follows: -| BSON type | BSON marker byte | JSON value type | -|-----------------------|------------------|-----------------| -| double | 0x01 | number_float | -| string | 0x02 | string | -| document | 0x03 | object | -| array | 0x04 | array | -| binary | 0x05 | binary | -| undefined | 0x06 | *unsupported* | -| ObjectId | 0x07 | *unsupported* | -| boolean | 0x08 | boolean | -| UTC Date-Time | 0x09 | *unsupported* | -| null | 0x0A | null | -| Regular Expr. | 0x0B | *unsupported* | -| DB Pointer | 0x0C | *unsupported* | -| JavaScript Code | 0x0D | *unsupported* | -| Symbol | 0x0E | *unsupported* | -| JavaScript Code | 0x0F | *unsupported* | -| int32 | 0x10 | number_integer | -| uint64(Timestamp) | 0x11 | number_unsigned | -| 128-bit decimal float | 0x13 | *unsupported* | -| Max Key | 0x7F | *unsupported* | -| Min Key | 0xFF | *unsupported* | +| BSON type | BSON marker byte | JSON value type | +|--------------------------|------------------|-----------------| +| double | 0x01 | number_float | +| string | 0x02 | string | +| document | 0x03 | object | +| array | 0x04 | array | +| binary | 0x05 | binary | +| undefined | 0x06 | *unsupported* | +| ObjectId | 0x07 | *unsupported* | +| boolean | 0x08 | boolean | +| UTC Date-Time | 0x09 | *unsupported* | +| null | 0x0A | null | +| Regular Expr. | 0x0B | *unsupported* | +| DB Pointer | 0x0C | *unsupported* | +| JavaScript Code | 0x0D | *unsupported* | +| Symbol | 0x0E | *unsupported* | +| JavaScript Code w/ scope | 0x0F | *unsupported* | +| int32 | 0x10 | number_integer | +| uint64(Timestamp) | 0x11 | number_unsigned | +| int64 | 0x12 | number_integer | +| 128-bit decimal float | 0x13 | *unsupported* | +| Max Key | 0x7F | *unsupported* | +| Min Key | 0xFF | *unsupported* | !!! warning "Incomplete mapping" diff --git a/docs/mkdocs/docs/features/binary_formats/cbor.md b/docs/mkdocs/docs/features/binary_formats/cbor.md index a4240ffad..1bd28c8da 100644 --- a/docs/mkdocs/docs/features/binary_formats/cbor.md +++ b/docs/mkdocs/docs/features/binary_formats/cbor.md @@ -5,7 +5,7 @@ extremely small code sizes, fairly small message size, and extensibility without !!! abstract "References" - - [CBOR Website](http://cbor.io) - the main source on CBOR + - [CBOR Website](http://cbor.io) - the main source on CBOR - [CBOR Playground](http://cbor.me) - an interactive webpage to translate between JSON and CBOR - [RFC 7049](https://tools.ietf.org/html/rfc7049) - the CBOR specification @@ -37,22 +37,22 @@ The library uses the following mapping from JSON values types to CBOR types acco | number_float | *any value representable by a float* | Single-Precision Float | 0xFA | | number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB | | string | *length*: 0..23 | UTF-8 string | 0x60..0x77 | -| string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 | +| string | *length*: 24..255 | UTF-8 string (1 byte follow) | 0x78 | | string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 | | string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A | | string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B | | array | *size*: 0..23 | array | 0x80..0x97 | -| array | *size*: 23..255 | array (1 byte follow) | 0x98 | +| array | *size*: 24..255 | array (1 byte follow) | 0x98 | | array | *size*: 256..65535 | array (2 bytes follow) | 0x99 | | array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A | | array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B | | object | *size*: 0..23 | map | 0xA0..0xB7 | -| object | *size*: 23..255 | map (1 byte follow) | 0xB8 | +| object | *size*: 24..255 | map (1 byte follow) | 0xB8 | | object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 | | object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA | | object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB | | binary | *size*: 0..23 | byte string | 0x40..0x57 | -| binary | *size*: 23..255 | byte string (1 byte follow) | 0x58 | +| binary | *size*: 24..255 | byte string (1 byte follow) | 0x58 | | binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 | | binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A | | binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B | diff --git a/docs/mkdocs/docs/features/binary_formats/index.md b/docs/mkdocs/docs/features/binary_formats/index.md index 6714965bd..ef79e2ef3 100644 --- a/docs/mkdocs/docs/features/binary_formats/index.md +++ b/docs/mkdocs/docs/features/binary_formats/index.md @@ -41,7 +41,7 @@ See [binary values](../binary_values.md) for more information. |--------------------|-------------|--------------|-------------------|---------------| | BJData | 53.2 % | 91.1 % | 78.1 % | 96.6 % | | BJData (size) | 58.6 % | 92.1 % | 86.7 % | 97.4 % | -| BJData (size+tyoe) | 58.6 % | 92.1 % | 86.5 % | 97.4 % | +| BJData (size+type) | 58.6 % | 92.1 % | 86.5 % | 97.4 % | | BSON | 85.8 % | 95.2 % | 95.8 % | 106.7 % | | CBOR | 50.5 % | 86.3 % | 68.4 % | 88.0 % | | MessagePack | 50.5 % | 86.0 % | 68.5 % | 87.9 % | diff --git a/docs/mkdocs/docs/features/binary_values.md b/docs/mkdocs/docs/features/binary_values.md index 260d67b54..79629383f 100644 --- a/docs/mkdocs/docs/features/binary_values.md +++ b/docs/mkdocs/docs/features/binary_values.md @@ -41,7 +41,7 @@ binary.has_subtype(); // returns false binary_with_subtype.has_subtype(); // returns true binary_with_subtype.clear_subtype(); -binary_with_subtype.has_subtype(); // returns true +binary_with_subtype.has_subtype(); // returns false binary_with_subtype.set_subtype(42); binary.set_subtype(23); @@ -146,7 +146,7 @@ as an array of uint8 values. The library implements this translation. auto v = json::to_bjdata(j); ``` - `v` is a `std::vector` with the following 20 elements: + `v` is a `std::vector` with the following 20 elements: ```c 0x7B // '{' @@ -158,10 +158,10 @@ as an array of uint8 values. The library implements this translation. 0x7D // '}' ``` - The following code uses the type and size optimization for UBJSON: + The following code uses the type and size optimization for BJData: ```cpp - // convert to UBJSON using the size and type optimization + // convert to BJData using the size and type optimization auto v = json::to_bjdata(j, true, true); ``` @@ -178,7 +178,7 @@ as an array of uint8 values. The library implements this translation. 0xCA 0xFE 0xBA 0xBE // content ``` - Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would + Note that subtype (42) is **not** serialized and that BJData has **no binary type**, and deserializing `v` would yield the following value: ```json @@ -205,7 +205,7 @@ unsigned 8-bit integer. If no subtype is given, the generic binary subtype 0x00 auto v = json::to_bson(j); ``` - `v` is a `std::vector` with the following 22 elements: + `v` is a `std::vector` with the following 22 elements: ```c 0x16 0x00 0x00 0x00 // number of bytes in the document @@ -247,7 +247,7 @@ byte array. auto v = json::to_cbor(j); ``` - `v` is a `std::vector` with the following 15 elements: + `v` is a `std::vector` with the following 15 elements: ```c 0xA1 // map(1) @@ -291,7 +291,7 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used. auto v = json::to_msgpack(j); ``` - `v` is a `std::vector` with the following 14 elements: + `v` is a `std::vector` with the following 14 elements: ```c 0x81 // fixmap1 @@ -331,7 +331,7 @@ as an array of uint8 values. The library implements this translation. auto v = json::to_ubjson(j); ``` - `v` is a `std::vector` with the following 20 elements: + `v` is a `std::vector` with the following 20 elements: ```c 0x7B // '{' diff --git a/docs/mkdocs/docs/features/conversions.md b/docs/mkdocs/docs/features/conversions.md new file mode 100644 index 000000000..eaa213324 --- /dev/null +++ b/docs/mkdocs/docs/features/conversions.md @@ -0,0 +1,91 @@ +# Converting values + +A `basic_json` value stores JSON data, but most of the time you want to move that data into ordinary C++ types (an +`#!cpp int`, a `#!cpp std::string`, a `#!cpp std::vector`, or one of your own structs) and back. This page describes how +these conversions work. + +## Getting values out + +The [`get`](../api/basic_json/get.md) function template returns a copy of the stored value converted to the requested +type: + +```cpp +json j = R"({"name": "Mary", "age": 42, "hobbies": ["hiking", "reading"]})"_json; + +auto name = j["name"].get(); // "Mary" +auto age = j["age"].get(); // 42 +auto hobbies = j["hobbies"].get>(); // {"hiking", "reading"} +``` + +!!! note "Getting a string without quotes" + + A frequent point of confusion: use [`get`](../api/basic_json/get.md), **not** [`dump`](serialization.md), to read a + string value. `#!cpp j["name"].get()` yields `#!cpp Mary`, whereas `#!cpp j["name"].dump()` yields the + JSON text `#!cpp "Mary"` (**with** quotes), because `dump` always produces a JSON text. + +Alternatively, [`get_to`](../api/basic_json/get_to.md) writes into an existing variable and deduces the target type, +which avoids repeating it: + +??? example + + ```cpp + --8<-- "examples/get_to.cpp" + ``` + + Output: + + ```json + --8<-- "examples/get_to.output" + ``` + +The library already knows how to convert to and from the scalar types and the STL containers (such as +`#!cpp std::vector`, `#!cpp std::map`, `#!cpp std::array`, `#!cpp std::optional`, and many more). Converting a JSON +object back to a `#!cpp std::map` or a JSON array back to a `#!cpp std::vector` therefore works without any extra code: + +```cpp +json j = {{"one", 1}, {"two", 2}}; +auto m = j.get>(); // {{"one", 1}, {"two", 2}} +``` + +## Implicit conversions + +By default, a JSON value implicitly converts to a compatible C++ type, so the explicit `get` call can often be omitted: + +```cpp +json j = "Hello"; +std::string s = j; // implicit conversion, same as j.get() +``` + +Implicit conversions are convenient but can be surprising (for example, in overload resolution or with `auto`). They can +be disabled by defining [`JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md) to `#!cpp 0`, +which forces the explicit `get` form and can catch unintended conversions at compile time. + +!!! warning "Conversions do not range-check numbers" + + Just like C++ itself, the `get` family performs numeric conversions without range checks — retrieving a + floating-point value as an integer truncates it, and narrowing conversions may overflow. See + [number conversion](types/number_handling.md#number-conversion) for details and how to guard against it. + +## Putting values in + +The reverse direction works the same way: assigning or constructing a `json` from a C++ value converts it to JSON. + +```cpp +std::vector numbers = {1, 2, 3}; +json j = numbers; // [1,2,3] +``` + +## Your own types + +The conversions above are built in for standard types. To make the same syntax work for **your own** types, provide +`to_json`/`from_json` functions (or use one of the convenience macros). This is described in detail on the +[arbitrary types conversions](arbitrary_types.md) page. Enums can be mapped to strings as described in +[specializing enum conversion](enum_conversion.md). + +## See also + +- [`get`](../api/basic_json/get.md) - get a copy converted to a given type +- [`get_to`](../api/basic_json/get_to.md) - convert into an existing variable +- [`get_ref`](../api/basic_json/get_ref.md) / [`get_ptr`](../api/basic_json/get_ptr.md) - access the stored value without copying +- [Arbitrary types conversions](arbitrary_types.md) - support your own types +- [`JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md) - toggle implicit conversions diff --git a/docs/mkdocs/docs/features/creating_values.md b/docs/mkdocs/docs/features/creating_values.md new file mode 100644 index 000000000..fc35b3401 --- /dev/null +++ b/docs/mkdocs/docs/features/creating_values.md @@ -0,0 +1,103 @@ +# Creating JSON values + +There are several ways to create a JSON value in memory. This page gives an overview; to read a value from JSON text +instead, see [parsing](parsing/index.md). + +## From C++ values + +Any value of a supported C++ type can be assigned to or used to construct a `json`: + +```cpp +json j_number = 42; +json j_float = 3.141; +json j_string = "Hello"; +json j_boolean = true; +json j_null = nullptr; +json j_vector = std::vector{1, 2, 3}; // array +``` + +See [converting values](conversions.md) for the full set of supported types. + +## With initializer lists + +Objects and arrays can be written concisely with brace-enclosed initializer lists: + +```cpp +// an array +json array = {1, 2, 3, 4}; + +// an object (a list of key/value pairs) +json object = { + {"pi", 3.141}, + {"happy", true}, + {"name", "Niels"}, + {"nothing", nullptr}, + {"list", {1, 0, 2}}, + {"object", {{"currency", "USD"}, {"value", 42.99}}} +}; +``` + +The library decides between an array and an object based on the content: a list whose elements are all two-element lists +with a string as the first element is treated as an object, everything else as an array. + +!!! warning "Ambiguous cases: `#!cpp {}` vs. `#!cpp []`" + + Because the same `#!cpp {}` syntax is used for both arrays and objects, some cases are ambiguous. To force a + particular type, use the explicit factory functions [`json::array`](../api/basic_json/array.md) and + [`json::object`](../api/basic_json/object.md): + + ```cpp + json empty_array_explicit = json::array(); // [] + json empty_object_explicit = json::object(); // {} + + // a JSON array with one object, not an object with one member + json array_of_objects = json::array({{"key", "value"}}); // [{"key":"value"}] + ``` + + Related to this, single-element brace initialization such as `#!cpp json j{value};` wraps the element in a + single-element **array** by default, and its behavior even differs between compilers. See the + [FAQ](../home/faq.md#brace-initialization-yields-arrays) for details and the opt-in + [`JSON_BRACE_INIT_COPY_SEMANTICS`](../api/macros/json_brace_init_copy_semantics.md) macro. + +## Building incrementally + +A value can also be built up piece by piece. Accessing a non-existing object key or array index with +[`operator[]`](element_access/unchecked_access.md) creates the element on the fly: + +```cpp +json j; // null +j["answer"]["everything"] = 42; // becomes an object +j["list"] = {1, 0, 2}; +j["list"].push_back(3); // [1,0,2,3] +``` + +See [modifying values](modifying_values.md) for [`push_back`](../api/basic_json/push_back.md), +[`emplace`](../api/basic_json/emplace.md), and related functions. + +## With the `_json` literal + +The `_json` [user-defined literal](../api/operator_literal_json.md) parses a string at the call site and is a +convenient way to write a JSON value inline: + +??? example + + ```cpp + --8<-- "examples/operator_literal_json.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_literal_json.output" + ``` + +Note this **parses** the string, so `#!cpp "42"_json` is the number `#!cpp 42`, whereas `#!cpp json("42")` is the JSON +string `#!json "42"`. + +## See also + +- [`basic_json` constructors](../api/basic_json/basic_json.md) - all ways to construct a value +- [`array`](../api/basic_json/array.md) / [`object`](../api/basic_json/object.md) - force array or object type +- [`operator""_json`](../api/operator_literal_json.md) - the `_json` literal +- [Converting values](conversions.md) - which C++ types can be used +- [Parsing](parsing/index.md) - create a value from JSON text diff --git a/docs/mkdocs/docs/features/element_access/checked_access.md b/docs/mkdocs/docs/features/element_access/checked_access.md index c4023cce5..1fb65e53b 100644 --- a/docs/mkdocs/docs/features/element_access/checked_access.md +++ b/docs/mkdocs/docs/features/element_access/checked_access.md @@ -29,7 +29,7 @@ otherwise. | `#!cpp j.at("hobbies").at(0)` | `#!json "hiking"` | | `#!cpp j.at("hobbies").at(1)` | `#!json "reading"` | -The return value is a reference, so it can be modified by the original value. +The return value is a reference, so it can be used to modify the original value. ??? example "Write access" @@ -62,7 +62,7 @@ non-existing, an exception is thrown. [json.exception.out_of_range.401] array index 3 is out of range ``` - When you [extended diagnostic messages](../../home/exceptions.md#extended-diagnostic-messages) are enabled by + When [extended diagnostic messages](../../home/exceptions.md#extended-diagnostic-messages) are enabled by defining [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md), the exception further gives information where the key or index is missing or out of range. diff --git a/docs/mkdocs/docs/features/element_access/default_value.md b/docs/mkdocs/docs/features/element_access/default_value.md index 01d6863c4..4f714a287 100644 --- a/docs/mkdocs/docs/features/element_access/default_value.md +++ b/docs/mkdocs/docs/features/element_access/default_value.md @@ -41,7 +41,7 @@ you want to access and a default value in case there is no value stored with tha The value function is a template, and the return type of the function is determined by the type of the provided default value unless otherwise specified. This can have unexpected effects. In the example below, we store a 64-bit unsigned integer. We get exactly that value when using [`operator[]`](../../api/basic_json/operator[].md). However, - when we call `value` and provide `#!c 0` as default value, then `#!c -1` is returned. The occurs, because `#!c 0` + when we call `value` and provide `#!c 0` as default value, then `#!c -1` is returned. This occurs, because `#!c 0` has type `#!c int` which overflows when handling the value `#!c 18446744073709551615`. To address this issue, either provide a correctly typed default value or use the template parameter to specify the diff --git a/docs/mkdocs/docs/features/index.md b/docs/mkdocs/docs/features/index.md new file mode 100644 index 000000000..0bbb2dadd --- /dev/null +++ b/docs/mkdocs/docs/features/index.md @@ -0,0 +1,53 @@ +# Features + +This section describes the features of the library in detail. If you are new to the library, the pages below are +roughly ordered along a typical workflow: create or parse a value, access and modify it, convert it to and from your own +C++ types, and finally serialize it again. + +## Creating and reading values + +- [Creating JSON values](creating_values.md) — build values from literals, initializer lists, and STL containers, and + understand the `#!cpp {}` vs. `#!cpp []` ambiguity. +- [Parsing](parsing/index.md) — read a JSON value from a string, file, or stream, including + [JSON Lines](parsing/json_lines.md), [callbacks](parsing/parser_callbacks.md), the + [SAX interface](parsing/sax_interface.md), and [error handling](parsing/parse_exceptions.md). +- [Comments](comments.md) and [trailing commas](trailing_commas.md) — opt-in relaxations of the JSON grammar. + +## Accessing and modifying values + +- [Element access](element_access/index.md) — unchecked ([`operator[]`](element_access/unchecked_access.md)), + checked ([`at`](element_access/checked_access.md)), and access with a + [default value](element_access/default_value.md). +- [JSON Pointer](json_pointer.md) — address values deep inside a document with [RFC 6901](https://tools.ietf.org/html/rfc6901) pointers. +- [Iterators](iterators.md) — traverse arrays and objects. +- [Modifying values](modifying_values.md) — add, update, merge, and remove elements. +- [JSON Patch and Diff](json_patch.md) and [JSON Merge Patch](merge_patch.md) — apply and compute structured changes. + +## Converting to and from C++ types + +- [Converting values](conversions.md) — get values out with [`get`](../api/basic_json/get.md)/[`get_to`](../api/basic_json/get_to.md), + and understand implicit conversions. +- [Arbitrary types conversions](arbitrary_types.md) — teach the library about your own structs and classes. +- [Specializing enum conversion](enum_conversion.md) — map enums to strings instead of integers. + +## Serializing values + +- [Serialization](serialization.md) — turn a value back into JSON text with [`dump`](../api/basic_json/dump.md), + including pretty-printing and handling of non-ASCII and invalid UTF-8. +- [Binary formats](binary_formats/index.md) — encode values more compactly as + [BJData](binary_formats/bjdata.md), [BSON](binary_formats/bson.md), [CBOR](binary_formats/cbor.md), + [MessagePack](binary_formats/messagepack.md), or [UBJSON](binary_formats/ubjson.md). +- [Binary values](binary_values.md) — store and exchange raw byte sequences. + +## How values are stored and configured + +- [Types](types/index.md) and [number handling](types/number_handling.md) — how JSON types map to C++ types and how + numbers are treated. +- [Object order](object_order.md) — keep insertion order with [`ordered_json`](../api/ordered_json.md). +- [Runtime assertions](assertions.md), [supported macros](macros.md), the [`nlohmann` namespace](namespace.md), and + [C++ modules](modules.md) — build-time and runtime configuration. + +!!! tip "Looking for a specific function?" + + This section gives conceptual overviews. For the precise signature, parameters, and return value of a function, see + the [API Documentation](../api/basic_json/index.md). diff --git a/docs/mkdocs/docs/features/iterators.md b/docs/mkdocs/docs/features/iterators.md index 6d8afc7f5..f45b92fdc 100644 --- a/docs/mkdocs/docs/features/iterators.md +++ b/docs/mkdocs/docs/features/iterators.md @@ -130,7 +130,7 @@ for (auto& [key, val] : j_object.items()) ### Iterating strings and binary values -Note that "value" means a JSON value in this setting, not values stored in the underlying containers. That is, `*begin()` returns the complete string or binary array and is also safe the underlying string or binary array is empty. +Note that "value" means a JSON value in this setting, not values stored in the underlying containers. That is, `*begin()` returns the complete string or binary array and is also safe if the underlying string or binary array is empty. ??? example diff --git a/docs/mkdocs/docs/features/json_patch.md b/docs/mkdocs/docs/features/json_patch.md index 88c731a2c..835f07f90 100644 --- a/docs/mkdocs/docs/features/json_patch.md +++ b/docs/mkdocs/docs/features/json_patch.md @@ -28,7 +28,7 @@ The library can also calculate a JSON patch (i.e., a **diff**) given two JSON va For two JSON values *source* and *target*, the following code yields always true: - ```cüü + ```cpp source.patch(diff(source, target)) == target; ``` diff --git a/docs/mkdocs/docs/features/modifying_values.md b/docs/mkdocs/docs/features/modifying_values.md new file mode 100644 index 000000000..23c0feb53 --- /dev/null +++ b/docs/mkdocs/docs/features/modifying_values.md @@ -0,0 +1,77 @@ +# Modifying values + +Once a JSON value exists, its content can be changed: elements can be added, replaced, merged, and removed. This page +gives an overview of the available operations. For read access, see [element access](element_access/index.md). + +## Adding to arrays + +New elements are appended to an array with [`push_back`](../api/basic_json/push_back.md) or constructed in place with +[`emplace_back`](../api/basic_json/emplace_back.md). If the value is `#!json null`, it is converted to an array first, so +these functions can also be used to build an array from scratch. + +```cpp +json j; // null +j.push_back(1); // [1] +j.push_back(2); // [1,2] +j.emplace_back(3); // [1,2,3] + +// operator+= is a shorthand for push_back +j += 4; // [1,2,3,4] +``` + +## Adding to objects + +The most common way to add or replace a member is [`operator[]`](element_access/unchecked_access.md), which inserts the +key if it does not exist yet: + +```cpp +json j; +j["name"] = "Mary"; // {"name":"Mary"} +j["name"] = "John"; // {"name":"John"} (replaced) +``` + +[`emplace`](../api/basic_json/emplace.md) inserts a member only if the key is not already present, and reports whether +the insertion happened — useful for "add if absent" semantics. + +## Merging objects + +To merge one object into another, [`update`](../api/basic_json/update.md) copies all members from another object, +overwriting existing keys (similar to Python's `dict.update`). This is the idiomatic way to combine two objects. + +??? example + + ```cpp + --8<-- "examples/update.cpp" + ``` + + Output: + + ```json + --8<-- "examples/update.output" + ``` + +For a recursive merge that follows [RFC 7386](https://tools.ietf.org/html/rfc7386), see +[JSON Merge Patch](merge_patch.md). To apply a sequence of well-defined edit operations, see +[JSON Patch](json_patch.md). + +## Removing elements + +Elements are removed with [`erase`](../api/basic_json/erase.md), which accepts an object key, an array index, or an +iterator. [`clear`](../api/basic_json/clear.md) empties a value while keeping its type, and +[`operator[]`](element_access/unchecked_access.md) combined with assignment can overwrite a value entirely. + +```cpp +json j = {{"a", 1}, {"b", 2}, {"c", 3}}; +j.erase("b"); // {"a":1,"c":3} + +json a = {1, 2, 3, 4}; +a.erase(1); // [1,3,4] (erase by index) +``` + +## See also + +- [`push_back`](../api/basic_json/push_back.md) / [`emplace_back`](../api/basic_json/emplace_back.md) - append to an array +- [`emplace`](../api/basic_json/emplace.md) - insert into an object if the key is absent +- [`update`](../api/basic_json/update.md) - merge objects +- [`erase`](../api/basic_json/erase.md) / [`clear`](../api/basic_json/clear.md) - remove elements +- [JSON Patch and Diff](json_patch.md) and [JSON Merge Patch](merge_patch.md) - structured modifications diff --git a/docs/mkdocs/docs/features/namespace.md b/docs/mkdocs/docs/features/namespace.md index 1a147ec30..5542c1f88 100644 --- a/docs/mkdocs/docs/features/namespace.md +++ b/docs/mkdocs/docs/features/namespace.md @@ -59,7 +59,7 @@ may complain about undefined references. Different versions are not necessarily ABI-incompatible, but the project does not actively track changes in the ABI and recommends that all parts of a codebase exchanging library types be built with the same version. Users can, **at their -own risk**, disable the version component of the linline namespace, allowing different versions – but not +own risk**, disable the version component of the inline namespace, allowing different versions – but not configurations – to be used in cases where the linker would otherwise output undefined reference errors. To do so, define [`NLOHMANN_JSON_NAMESPACE_NO_VERSION`](../api/macros/nlohmann_json_namespace_no_version.md) to `1`. @@ -71,6 +71,7 @@ section to emulate the effect of the `NLOHMANN_JSON_NAMESPACE_NO_VERSION` macro. Disabling the namespace version component and mixing ABI-incompatible versions will result in crashes or incorrect behavior. You have been warned! + ## Disabling the inline namespace completely When interoperability with code using a pre-3.11.0 version of the library is required, users can, **at their own risk** diff --git a/docs/mkdocs/docs/features/object_order.md b/docs/mkdocs/docs/features/object_order.md index 63914188f..ac5eb7beb 100644 --- a/docs/mkdocs/docs/features/object_order.md +++ b/docs/mkdocs/docs/features/object_order.md @@ -37,7 +37,7 @@ The default type `nlohmann::json` uses a `std::map` to store JSON objects, and t ## Alternative behavior: preserve insertion order -If you do want to preserve the **insertion order**, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179). +If you do want to preserve the **insertion order**, you can use the type [`nlohmann::ordered_json`](../api/ordered_json.md). ??? example @@ -103,7 +103,7 @@ Assume file `input.json` contains the JSON object above: ```json { "one": 1, - "three": 3 - "two": 2, + "three": 3, + "two": 2 } ``` diff --git a/docs/mkdocs/docs/features/parsing/index.md b/docs/mkdocs/docs/features/parsing/index.md index 29493520e..c3cb88f63 100644 --- a/docs/mkdocs/docs/features/parsing/index.md +++ b/docs/mkdocs/docs/features/parsing/index.md @@ -1,13 +1,61 @@ # Parsing -!!! note - - This page is under construction. +This library can create a JSON value from a wide range of inputs. This page gives an overview of the available parsing +functions and how they behave; the linked pages go into more detail. ## Input +The [`parse`](../../api/basic_json/parse.md) function reads a JSON value from an input. The input can be + +- a string (`#!cpp std::string`, C string, or string literal), +- a `#!cpp std::istream` (e.g., an `#!cpp std::ifstream` reading from a file), +- a `#!cpp FILE*` pointer, +- a pair of iterators over a contiguous range (e.g., a `#!cpp std::vector`), or +- a contiguous container. + +```cpp +// parse from a string +json j = json::parse(R"({"happy": true, "pi": 3.141})"); + +// parse from a file +std::ifstream f("example.json"); +json data = json::parse(f); +``` + +The input must be encoded in UTF-8; other encodings are not supported. A single input may contain only one JSON value. +Inputs consisting of multiple values separated by newlines are handled by the [JSON Lines](json_lines.md) format. + +By default, the library rejects comments and trailing commas. Both can be enabled with parameters of the `parse` +function — see [comments](../comments.md) and [trailing commas](../trailing_commas.md). + ## SAX vs. DOM parsing +The library offers two parsing models: + +- **DOM parsing** (the default): the complete input is read and stored as an in-memory `basic_json` value that can be + traversed and modified freely. This is what [`parse`](../../api/basic_json/parse.md) does, and it is the right choice + for most use cases. +- **SAX parsing**: instead of building a value, the parser reports events (such as "a string was read" or "an object + started") to a handler that you implement. This avoids building the full value in memory and is useful for very large + inputs or when you only need to extract parts of the input. See the [SAX interface](sax_interface.md) for details and + [`sax_parse`](../../api/basic_json/sax_parse.md) for the API. + +You can influence a DOM parse without switching to the SAX interface by passing a +[parser callback](parser_callbacks.md), which is called during parsing and can, for example, discard parts of the input. + ## Exceptions -See [parsing and exceptions](parse_exceptions.md). +When the input is not valid JSON, the `parse` function throws an exception by default. If exceptions are undesired or +unavailable, the parser can instead return a discarded value, or [`accept`](../../api/basic_json/accept.md) can be used +to only check whether an input is valid JSON. See [parsing and exceptions](parse_exceptions.md) for the available +options. + +## See also + +- [`parse`](../../api/basic_json/parse.md) - deserialize from a compatible input +- [`accept`](../../api/basic_json/accept.md) - check if the input is valid JSON +- [`sax_parse`](../../api/basic_json/sax_parse.md) - generate SAX events +- [JSON Lines](json_lines.md) - parse newline-delimited JSON +- [parser callbacks](parser_callbacks.md) - influence the parsing by a callback function +- [SAX interface](sax_interface.md) - implement a custom SAX handler +- [parsing and exceptions](parse_exceptions.md) - control error handling diff --git a/docs/mkdocs/docs/features/serialization.md b/docs/mkdocs/docs/features/serialization.md new file mode 100644 index 000000000..a875fcdde --- /dev/null +++ b/docs/mkdocs/docs/features/serialization.md @@ -0,0 +1,129 @@ +# Serialization + +Serialization is the process of turning a JSON value back into JSON text. It is the counterpart to +[parsing](parsing/index.md). The central function is [`dump`](../api/basic_json/dump.md), which returns the JSON text as +a string. + +```cpp +json j = {{"pi", 3.141}, {"happy", true}}; + +std::string s = j.dump(); // {"happy":true,"pi":3.141} +``` + +To write a value directly to a stream (for example, a file or `#!cpp std::cout`), the +[`operator<<`](../api/operator_ltlt.md) is provided: + +```cpp +std::cout << j << std::endl; +``` + +!!! note "String, not raw value" + + `dump` always returns a **JSON text**. Serializing a JSON string therefore includes the surrounding quotes and + escapes special characters. To obtain the *contained* string value without quotes, use + [`get()`](conversions.md) instead of `dump`. See the [converting values](conversions.md) page. + +## Pretty-printing + +By default, `dump` produces the most compact representation without any superfluous whitespace. Passing a non-negative +`indent` argument pretty-prints the output with the given number of spaces per level: + +??? example + + ```cpp + --8<-- "examples/dump.cpp" + ``` + + Output: + + ```json + --8<-- "examples/dump.output" + ``` + +The indentation character can be changed with the second argument (e.g., a tab `#!cpp '\t'`). An `indent` of `0` inserts +newlines but no leading spaces, and the default of `#!cpp -1` selects the compact single-line form. + +## Non-ASCII characters + +Strings are stored and serialized as UTF-8 (see [types](types/index.md#strings)). By default, `dump` copies valid +non-ASCII characters as-is. Setting the third argument `ensure_ascii` to `#!cpp true` escapes all non-ASCII characters +with `\uXXXX` sequences, so that the output contains only ASCII characters: + +```cpp +json j = "苹果"; +j.dump(); // "苹果" +j.dump(-1, ' ', true); // "苹果" +``` + +## Handling invalid UTF-8 + +If a string contains invalid UTF-8 sequences (for example, because it holds data in another encoding such as Latin-1), +serialization fails by default. The fourth argument of `dump` selects an +[`error_handler`](../api/basic_json/error_handler_t.md): + +- `strict` (default) — throw a [`type_error.316`](../home/exceptions.md#jsonexceptiontype_error316) exception. +- `replace` — replace invalid bytes with the Unicode replacement character U+FFFD (`�`). +- `ignore` — silently drop invalid bytes. + +??? example + + ```cpp + --8<-- "examples/error_handler_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/error_handler_t.output" + ``` + +!!! tip "Avoiding invalid UTF-8" + + The best fix is to ensure that all strings are UTF-8 encoded before storing them. See the + [FAQ on non-ASCII characters](../home/faq.md#parse-errors-reading-non-ascii-characters) for how to convert wide or + Latin-1 strings. + +## Numbers, NaN, and binary values + +- **Numbers** are serialized with enough precision to round-trip; see [number serialization](types/number_handling.md#number-serialization). +- **NaN and infinity** cannot be represented in JSON and are serialized as `#!json null`; see + [NaN handling](types/number_handling.md#nan-handling). The [binary formats](binary_formats/index.md) can preserve + them. +- **Binary values** have no JSON representation and are serialized as a helper object for debugging only; see + [binary values](binary_values.md#serialization). + +## Using `std::format`, `std::print`, and `fmt` + +Since version 3.12.0, JSON values can be formatted directly with C++20's +[`std::format`](https://en.cppreference.com/w/cpp/utility/format/format) whenever the standard library provides the +`` header (controlled by [`JSON_HAS_STD_FORMAT`](../api/macros/json_has_std_format.md)). This is enabled by the +[`std::formatter`](../api/basic_json/std_formatter.md) specialization, which also makes JSON values work with +`std::format_to` and with C++23's `std::print`/`std::println`: + +```cpp +std::print("{}", j); // compact, like j.dump() +std::print("{:2}", j); // pretty-printed with indent 2 (like j.dump(2)) +std::println("{:#}", j); // pretty-printed with the default indent +``` + +The format spec mirrors the `dump` parameters: `#!cpp "{:#}"` pretty-prints, a width such as `#!cpp "{:2}"` sets the +indent, and a fill-and-align prefix such as `#!cpp "{:.>#}"` sets the indent character. + +For the [{fmt}](https://github.com/fmtlib/fmt) library, the library ships a +[`format_as`](../api/basic_json/format_as.md) helper. Note its behavior depends on the `fmt` version; see the +[FAQ entry](../home/faq.md#using-json-values-with-stdformat-or-fmt) for the details and a recipe for a full +`fmt::formatter` specialization. + +## Serializing to other formats + +Besides JSON text, a value can also be serialized to the more compact [binary formats](binary_formats/index.md) +(BJData, BSON, CBOR, MessagePack, UBJSON). + +## See also + +- [`dump`](../api/basic_json/dump.md) - serialize to a JSON-formatted string +- [`operator<<`](../api/operator_ltlt.md) - serialize to a stream +- [`to_string`](../api/basic_json/to_string.md) - user-defined-conversion helper +- [`std::formatter`](../api/basic_json/std_formatter.md) - use JSON values with `std::format` and `std::print` +- [`format_as`](../api/basic_json/format_as.md) - use JSON values with the {fmt} library +- [Parsing](parsing/index.md) - the reverse operation diff --git a/docs/mkdocs/docs/features/types/index.md b/docs/mkdocs/docs/features/types/index.md index 56fb7ebe9..78e332936 100644 --- a/docs/mkdocs/docs/features/types/index.md +++ b/docs/mkdocs/docs/features/types/index.md @@ -137,7 +137,7 @@ The choice of `object_t` influences the behavior of the JSON class. With the def ### Key order -The order name/value pairs are added to the object are *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON objects. +The order in which name/value pairs are added to the object is *not* preserved by the library. Therefore, iterating an object may return name/value pairs in a different order than they were originally stored. In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default. Please note this behavior conforms to [RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON objects. ### Limits diff --git a/docs/mkdocs/docs/features/types/number_handling.md b/docs/mkdocs/docs/features/types/number_handling.md index a02c1d3a9..7fa31fb97 100644 --- a/docs/mkdocs/docs/features/types/number_handling.md +++ b/docs/mkdocs/docs/features/types/number_handling.md @@ -91,7 +91,7 @@ This is the same behavior as the code `#!c double x = 3.141592653589793238462643 !!! success "Interoperability" - - The library interoperable with respect to the specification, because its supported range $[-2^{63}, 2^{64}-1]$ is + - The library is interoperable with respect to the specification, because its supported range $[-2^{63}, 2^{64}-1]$ is larger than the described range $[-2^{53}+1, 2^{53}-1]$. - All integers outside the range $[-2^{63}, 2^{64}-1]$, as well as floating-point numbers are stored as `double`. This also concurs with the specification above. @@ -153,7 +153,7 @@ NaN (not-a-number) cannot be expressed with the number syntax described above an That is, there is no way to *parse* a NaN value. However, assignments can store NaN values in a JSON value. -This library serializes NaN values as `#!js null`. This corresponds to the behavior of JavaScript's +This library serializes NaN values as `#!js null`. This corresponds to the behavior of JavaScript's [`JSON.stringify`](https://www.w3schools.com/js/js_json_stringify.asp) function. !!! example @@ -182,7 +182,7 @@ This library serializes NaN values as `#!js null`. This corresponds to the beha ### Number comparison -Floating-point inside JSON values numbers are compared with `#!c json::number_float_t::operator==` which is +Floating-point numbers inside JSON values are compared with `#!c json::number_float_t::operator==` which is `#!c double::operator==` by default. !!! example "Alternative comparison functions" @@ -203,8 +203,8 @@ Floating-point inside JSON values numbers are compared with `#!c json::number_fl ```cpp bool my_equal(const_reference lhs, const_reference rhs) { - const auto lhs_type lhs.type(); - const auto rhs_type rhs.type(); + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); if (lhs_type == rhs_type) { switch(lhs_type) @@ -230,7 +230,7 @@ Floating-point inside JSON values numbers are compared with `#!c json::number_fl ### Number conversion Just like the C++ language itself, the `get` family of functions allows conversions between unsigned and signed -integers, and between integers and floating-point values to integers. This behavior may be surprising. +integers, and between integers and floating-point values. This behavior may be surprising. !!! warning "Unconditional number conversions" diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index 5848926cc..7f68ea548 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -57,6 +57,7 @@ nav: - home/customers.md - home/sponsors.md - Features: + - features/index.md - features/arbitrary_types.md - Binary Formats: - features/binary_formats/index.md @@ -67,16 +68,18 @@ nav: - features/binary_formats/ubjson.md - features/binary_values.md - features/comments.md - - features/trailing_commas.md + - features/conversions.md + - features/creating_values.md - Element Access: - features/element_access/index.md - features/element_access/unchecked_access.md - features/element_access/checked_access.md - features/element_access/default_value.md - features/iterators.md - - features/json_pointer.md - - features/json_patch.md - features/merge_patch.md + - features/json_patch.md + - features/json_pointer.md + - features/modifying_values.md - features/modules.md - 'nlohmann Namespace': features/namespace.md - features/object_order.md @@ -87,8 +90,10 @@ nav: - features/parsing/parser_callbacks.md - features/parsing/sax_interface.md - features/assertions.md + - features/serialization.md - features/enum_conversion.md - features/macros.md + - features/trailing_commas.md - Types: - features/types/index.md - features/types/number_handling.md