📝 update documentation (#4723)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2025-04-05 18:54:35 +02:00
committed by GitHub
parent 11aa5f944d
commit 4424a0fcc1
90 changed files with 377 additions and 339 deletions

View File

@@ -88,13 +88,13 @@ If you just want to serialize/deserialize some structs, the `to_json`/`from_json
There are six macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from an object which is default-constructed by the type.
- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It does not define a `from_json()` function which is needed in case the type does not have a default constructor.
- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from an object which is default-constructed by the type.
- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It does not define a `from_json()` function which is needed in case the type does not have a default constructor.
Furthermore, there exist versions to use in case of derived classes:
Furthermore, there exist versions to use in the case of derived classes:
| Need access to private members | Need only de-serialization | Allow missing values when de-serializing | macro |
|------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
@@ -149,9 +149,9 @@ For _derived_ classes and structs, use the following macros
## How do I convert third-party types?
This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
This requires a bit more advanced technique. But first, let us see how this conversion mechanism works:
The library uses **JSON Serializers** to convert types to json.
The library uses **JSON Serializers** to convert types to JSON.
The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)).
It is implemented like this (simplified):
@@ -206,7 +206,7 @@ NLOHMANN_JSON_NAMESPACE_END
## How can I use `get()` for non-default constructible/non-copyable types?
There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
There is a way if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
```cpp
struct move_only_type {
@@ -241,7 +241,7 @@ namespace nlohmann {
Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-udt.cpp) in the test suite, to see a few examples.
If you write your own serializer, you'll need to do a few things:
If you write your own serializer, you will need to do a few things:
- use a different `basic_json` alias than `nlohmann::json` (the last template parameter of `basic_json` is the `JSONSerializer`)
- use your `basic_json` alias (or a template parameter) in all your `to_json`/`from_json` methods

View File

@@ -1,7 +1,7 @@
# Runtime Assertions
The code contains numerous debug assertions to ensure class invariants are valid or to detect undefined behavior.
Whereas the former class invariants are nothing to be concerned of, the latter checks for undefined behavior are to
Whereas the former class invariants are nothing to be concerned with, the latter checks for undefined behavior are to
detect bugs in client code.
## Switch off runtime assertions
@@ -19,8 +19,8 @@ before including the `json.hpp` header.
### Unchecked object access to a const value
Function [`operator[]`](../api/basic_json/operator%5B%5D.md) implements unchecked access for objects. Whereas a missing
key is added in case of non-const objects, accessing a const object with a missing key is undefined behavior (think of a
dereferenced null pointer) and yields a runtime assertion.
key is added in the case of non-const objects, accessing a const object with a missing key is undefined behavior (think
of a dereferenced null pointer) and yields a runtime assertion.
If you are not sure whether an element in an object exists, use checked access with the
[`at` function](../api/basic_json/at.md) or call the [`contains` function](../api/basic_json/contains.md) before.
@@ -107,9 +107,9 @@ behavior and yields a runtime assertion.
### Reading from a null `FILE` or `char` pointer
Reading from a null `#!cpp FILE` or `#!cpp char` pointer in C++ is undefined behavior. Until version 3.11.4, this
Reading from a null `#!cpp FILE` or `#!cpp char` pointer in C++ is undefined behavior. Until version 3.12.0, this
library asserted that the pointer was not `nullptr` using a runtime assertion. If assertions were disabled, this would
result in undefined behavior. Since version 3.11.4, this library checks for `nullptr` and throws a
result in undefined behavior. Since version 3.12.0, this library checks for `nullptr` and throws a
[`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) to prevent the undefined behavior.
??? example "Example 4: Reading from null pointer"

View File

@@ -5,12 +5,12 @@ The [BJData format](https://neurojson.org) was derived from and improved upon
array container for efficient storage of N-dimensional packed arrays (**ND-arrays**); it also adds 5 new type markers -
`[u] - uint16`, `[m] - uint32`, `[M] - uint64`, `[h] - float16` and `[B] - byte` - to unambiguously map common binary
numeric types; furthermore, it uses little-endian (LE) to store all numerics instead of big-endian (BE) as in UBJSON to
avoid unnecessary conversions on commonly available platforms.
avoid unnecessary conversions on commonly available platforms.
Compared to other binary JSON-like formats such as MessagePack and CBOR, both BJData and UBJSON demonstrate a rare
combination of being both binary and **quasi-human-readable**. This is because all semantic elements in BJData and
UBJSON, including the data-type markers and name/string types are directly human-readable. Data stored in the
BJData/UBJSON format are not only compact in size, fast to read/write, but also can be directly searched or read using
UBJSON, including the data-type markers and name/string types, are directly human-readable. Data stored in the
BJData/UBJSON format is not only compact in size, fast to read/write, but also can be directly searched or read using
simple processing.
!!! abstract "References"

View File

@@ -1,6 +1,6 @@
# Binary Formats
Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over
Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance, over
a network. Hence, the library supports
- [BJData](bjdata.md) (Binary JData),

View File

@@ -5,7 +5,7 @@ these formats support binary values; that is, values that have semantics define
sequence of bytes to be stored.
JSON itself does not have a binary value. As such, binary values are an extension that this library implements to store
values received by a binary format. Binary values are never created by the JSON parser, and are only part of a
values received by a binary format. Binary values are never created by the JSON parser and are only part of a
serialized JSON text if they have been created manually or via a binary format.
## API for binary values
@@ -130,8 +130,8 @@ is an integer or `null`.
### BJData
[BJData](binary_formats/bjdata.md) neither supports binary values nor subtypes, and proposes to serialize binary values
as array of uint8 values. This translation is implemented by the library.
[BJData](binary_formats/bjdata.md) neither supports binary values nor subtypes and proposes to serialize binary values
as an array of uint8 values. The library implements this translation.
??? example
@@ -315,8 +315,8 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used.
### UBJSON
[UBJSON](binary_formats/ubjson.md) neither supports binary values nor subtypes, and proposes to serialize binary values
as array of uint8 values. This translation is implemented by the library.
[UBJSON](binary_formats/ubjson.md) neither supports binary values nor subtypes and proposes to serialize binary values
as an array of uint8 values. The library implements this translation.
??? example

View File

@@ -9,7 +9,7 @@ This library does not support comments *by default*. It does so for three reason
> Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser.
3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
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 pass set parameter `ignore_comments` to `#!c true` in the parse function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.

View File

@@ -2,7 +2,7 @@
## Overview
In many situations such as configuration files, missing values are not exceptional, but may be treated as if a default
In many situations, such as configuration files, missing values are not exceptional, but may be treated as if a default
value was present. For this case, use [`value(key, default_value)`](../../api/basic_json/value.md) which takes the key
you want to access and a default value in case there is no value stored with that key.

View File

@@ -29,7 +29,7 @@ similar to a `#!cpp std::map` and a `#!cpp std::vector`, respectively.
| `#!cpp j["hobbies"][1]` | `#!json "reading"` |
The return value is a reference, so it can modify the original value. In case the passed object key is non-existing, a
`#!json null` value is inserted which can be immediately be overwritten.
`#!json null` value is inserted which can immediately be overwritten.
??? example "Write access"

View File

@@ -1,7 +1,7 @@
# Specializing enum conversion
By default, enum values are serialized to JSON as integers. In some cases this could result in undesired behavior. If an
enum is modified or re-ordered after data has been serialized to JSON, the later de-serialized JSON data may be
enum is modified or re-ordered after data has been serialized to JSON, the later deserialized JSON data may be
undefined or a different enum value than was originally intended.
It is possible to more precisely specify how a given enum is mapped to and from JSON as shown below:

View File

@@ -2,8 +2,8 @@
## Introduction
The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address
structured values. A JSON Pointer is a string that identifies a specific value within a JSON document.
The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as an alternative means to
address structured values. A JSON Pointer is a string that identifies a specific value within a JSON document.
Consider the following JSON document

View File

@@ -34,7 +34,7 @@ See [full documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md
When enabled, two new member functions [`start_pos()`](../api/basic_json/start_pos.md) and
[`end_pos()`](../api/basic_json/end_pos.md) are added to [`basic_json`](../api/basic_json/index.md) values. If the value
was created by calling the[`parse`](../api/basic_json/parse.md) function, then these functions allow to query the byte
was created by calling the[`parse`](../api/basic_json/parse.md) function, then these functions allow querying the byte
positions of the value in the input it was parsed from. The byte positions are also used in exceptions to help locate
errors.
@@ -92,8 +92,8 @@ See [full documentation of `JSON_SKIP_LIBRARY_VERSION_CHECK`](../api/macros/json
## `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`
When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to
use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used.
When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows
using the library with compilers that do not fully support C++11 and may only work if unsupported features are not used.
See [full documentation of `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`](../api/macros/json_skip_unsupported_compiler_check.md).

View File

@@ -1,6 +1,6 @@
# Types
This page gives an overview how JSON values are stored and how this can be configured.
This page gives an overview of how JSON values are stored and how this can be configured.
## Overview
@@ -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 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.
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.
### Limits
@@ -202,7 +202,7 @@ Strings are stored in UTF-8 encoding. Therefore, functions like `std::string::si
[RFC 8259](https://tools.ietf.org/html/rfc8259) states:
> Software implementations are typically required to test names of object members for equality. Implementations that transform the textual representation into sequences of Unicode code units and then perform the comparison numerically, code unit by code unit, are interoperable in the sense that implementations will agree in all cases on equality or inequality of two strings. For example, implementations that compare strings with escaped characters unconverted may incorrectly find that `"a\\b"` and `"a\u005Cb"` are not equal.
> Software implementations are typically required to test names of object members for equality. Implementations that transform the textual representation into sequences of Unicode code units and then perform the comparison numerically, code unit by code unit are interoperable in the sense that implementations will agree in all cases on equality or inequality of two strings. For example, implementations that compare strings with escaped characters unconverted may incorrectly find that `"a\\b"` and `"a\u005Cb"` are not equal.
This implementation is interoperable as it does compare strings code unit by code unit.
@@ -231,7 +231,7 @@ See the [number handling](number_handling.md) article for a detailed discussion
> The representation of numbers is similar to that used in most programming languages. A number is represented in base 10 using decimal digits. It contains an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part. Leading zeros are not allowed. (...) Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted.
This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer or a floating-point number. Therefore, three different types, `number_integer_t`, `number_unsigned_t`, and `number_float_t` are used.
This description includes both integer and floating-point numbers. However, C++ allows more precise storage if it is known whether the number is a signed integer, an unsigned integer, or a floating-point number. Therefore, three different types, `number_integer_t`, `number_unsigned_t`, and `number_float_t` are used.
### Default types
@@ -241,7 +241,7 @@ With the default values for *NumberFloatType* (`#!cpp double`), the default valu
### Default behavior
- The restrictions about leading zeros is not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as octal number. Internally, the value will be stored as decimal number. For instance, the C++ integer literal `#!c 010` will be serialized to `#!c 8`. During deserialization, leading zeros yield an error.
- The restrictions about leading zeros are not enforced in C++. Instead, leading zeros in integer literals lead to an interpretation as an octal number. Internally, the value will be stored as a decimal number. For instance, the C++ integer literal `#!c 010` will be serialized to `#!c 8`. During deserialization, leading zeros yield an error.
- Not-a-number (NaN) values will be serialized to `#!json null`.
### Limits
@@ -250,9 +250,9 @@ With the default values for *NumberFloatType* (`#!cpp double`), the default valu
> An implementation may set limits on the range and precision of numbers.
When the default type is used, the maximal integer number that can be stored is `#!c 9223372036854775807` (`INT64_MAX`) and the minimal integer number that can be stored is `#!c -9223372036854775808` (`INT64_MIN`). Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as `number_unsigned_t` or `number_float_t`.
When the default type is used, the maximal integer number that can be stored is `#!c 9223372036854775807` (`INT64_MAX`) and the minimal integer number that can be stored is `#!c -9223372036854775808` (`INT64_MIN`). Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will automatically be stored as `number_unsigned_t` or `number_float_t`.
When the default type is used, the maximal unsigned integer number that can be stored is `#!c 18446744073709551615` (`UINT64_MAX`) and the minimal integer number that can be stored is `#!c 0`. Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will be automatically be stored as `number_integer_t` or `number_float_t`.
When the default type is used, the maximal unsigned integer number that can be stored is `#!c 18446744073709551615` (`UINT64_MAX`) and the minimal integer number that can be stored is `#!c 0`. Integer numbers that are out of range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers will automatically be stored as `number_integer_t` or `number_float_t`.
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:

View File

@@ -54,13 +54,13 @@ On number interoperability, the following remarks are made:
## Library implementation
This section describes how the above number specification is implemented by this library.
This section describes how this library implements the above number specification.
### Number storage
In the default [`json`](../../api/json.md) type, numbers are stored as `#!c std::uint64_t`, `#!c std::int64_t`, and
`#!c double`, respectively. Thereby, `#!c std::uint64_t` and `#!c std::int64_t` are used only if they can store the
number without loss of precision. If this is impossible (e.g., if the number is too large), the number is stored as
`#!c double`, respectively. Thereby, `#!c std::uint64_t` and `#!c std::int64_t` are used only if they can store the
number without loss of precision. If this is impossible (e.g., if the number is too large), the number is stored as
`#!c double`.
!!! info "Notes"
@@ -116,7 +116,7 @@ That is, `-0` is stored as a signed integer, but the serialization does not repr
- Integer numbers are serialized as is; that is, no scientific notation is used.
- Floating-point numbers are serialized as specified by the `#!c %g` printf modifier with
[`std::numeric_limits<double>::max_digits10`](https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10)
significant digits. The rationale is to use the shortest representation while still allow round-tripping.
significant digits. The rationale is to use the shortest representation while still allowing round-tripping.
!!! hint "Notes regarding precision of floating-point numbers"
@@ -151,7 +151,7 @@ NaN (not-a-number) cannot be expressed with the number syntax described above an
Numeric values that cannot be represented in the grammar below (such
as Infinity and NaN) are not permitted.
That is, there is no way to *parse* a NaN value. However, NaN values can be stored in a JSON value by assignment.
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
[`JSON.stringify`](https://www.w3schools.com/js/js_json_stringify.asp) function.
@@ -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 to integers. This behavior may be surprising.
!!! warning "Unconditional number conversions"
@@ -246,7 +246,7 @@ integers, and between integers and floating-point values to integers. This beha
The rationale is twofold:
1. JSON does not define a number type or precision (see above).
2. C++ also allows to silently convert between number types.
2. C++ also allows silently converting between number types.
!!! success "Conditional number conversion"