Compare commits

..
Author SHA1 Message Date
Niels Lohmann 7b2a1b2de5 Docs: fill documentation gaps found in user questions
Add pages on class-hierarchy/smart-pointer/variant/chrono recipes, working
without exceptions, and large, streamed and partial input. Extend the FAQ
(23 entries, Known bugs first), parse error documentation (empty-input
checklist, line/column, diagnostic positions), element access, conversions,
creating values, ADL troubleshooting, memory, and build/distribution notes.
Add 14 examples with generated output. Correct the statement that parse errors
cannot be recovered from with -fno-exceptions.

The topics come from recurring questions on Stack Overflow, Reddit, Hacker
News, YouTube, and the project's GitHub discussions and issues.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-24 19:13:49 +02:00
168 changed files with 2228 additions and 1717 deletions

No files matched your search

@@ -30,14 +30,6 @@ struct adl_serializer {
- [**from_json**](from_json.md) - convert a JSON value to any value type
- [**to_json**](to_json.md) - convert any value type to a JSON value
## See also
- [Arbitrary type conversions](../../features/arbitrary_types.md) - how to make your types convertible
- [**get**](../basic_json/get.md) / [**get_to**](../basic_json/get_to.md) - convert a JSON value to a C++ type
- [**basic_json**](../basic_json/basic_json.md) - construct a JSON value from a C++ value
- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE**](../macros/nlohmann_define_type_intrusive.md) - generate the conversion functions for a type
- [Specializing enum conversion](../../features/enum_conversion.md)
## Version history
- Added in version 2.1.0.
+1 -25
View File
@@ -23,9 +23,6 @@ Checks whether the input is valid JSON.
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
the iterator type with `operator!=`.
Ill-formed UTF-16 and UTF-32 sequences are rejected: a lone surrogate, a high surrogate that is not followed by its
low surrogate, and a code point above `U+10FFFF` all make this function return `false`.
Unlike the [`parse()`](parse.md) function, this function neither throws an exception in case of invalid JSON input
(i.e., a parse error) nor creates diagnostic information.
@@ -38,12 +35,9 @@ Unlike the [`parse()`](parse.md) function, this function neither throws an excep
- a `#!c FILE` pointer (throws if null)
- a C-style array of characters
- a pointer to a null-terminated string of single byte characters (throws if null)
- a `std::string` or a `std::string_view` (C++17)
- a `std::string`
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
- wide characters (`wchar_t`, `char16_t`, `char32_t`), which are converted to UTF-8: a wide string object
(`std::wstring`, `std::u16string`, `std::u32string`) or an array (e.g. a wide string literal); a pointer to a
null-terminated wide string (e.g. `std::u16string::c_str()`) is not supported
`IteratorType`
: a compatible iterator type, for instance.
@@ -131,21 +125,6 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
--8<-- "examples/accept__iterator_pair.output"
```
??? example "Example: (3) reading from UTF-16 strings"
The encoding is deduced from the character type of the input. String literals like `u"..."`, `U"..."`, and
`L"..."` work as well.
```cpp
--8<-- "examples/accept__wide_string.cpp"
```
Output:
```json
--8<-- "examples/accept__wide_string.output"
```
## See also
- [parse](parse.md) - deserialize from a compatible input
@@ -172,9 +151,6 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
([`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md)).
- Parsing from a `FILE*` locks the file once instead of once per character in version 3.13.0
([`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md)).
- Ill-formed UTF-16 and UTF-32 input (a lone surrogate, a high surrogate that is not followed by its low surrogate, or
a code point above `U+10FFFF`) is rejected in version 3.13.0; before that, some such sequences were accepted or
ended the input silently.
!!! warning "Deprecation"
+3 -2
View File
@@ -239,8 +239,9 @@ Strong exception safety: if an exception occurs, the original value stays intact
1. Added in version 1.0.0.
2. Added in version 1.0.0.
3. Added in version 3.11.0. Support for keys convertible to `std::string_view` added in version 3.13.0, consistently
across the lookup functions.
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
already supported by [`operator[]`](operator[].md), [`value`](value.md), [`find`](find.md), and other lookup
functions.
4. Added in version 2.0.0. Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) for a one-character array index that is not
a digit (e.g., `/x`) in version 3.13.0, as it already did for longer ones.
+1 -1
View File
@@ -63,4 +63,4 @@ Constant.
## Version history
- Added in version 1.0.0.
- Binary values are supported since version 3.8.0.
- Adjusted code to return reference to binary values in version 3.8.0.
@@ -482,15 +482,15 @@ basic_json(basic_json&& other) noexcept;
## Version history
1. Added in version 1.0.0.
2. Added in version 1.0.0.
3. Added in version 2.1.0.
4. Added in version 3.1.2. Explicit for different string types if `JSON_USE_IMPLICIT_CONVERSIONS` is `0` since
1. Since version 1.0.0.
2. Since version 1.0.0.
3. Since version 2.1.0.
4. Since version 3.2.0. Explicit for different string types if `JSON_USE_IMPLICIT_CONVERSIONS` is `0` since
version 3.13.0.
5. Added in version 1.0.0.
6. Added in version 1.0.0.
7. Added in version 1.0.0. Fixed in version 3.13.0 to also check the iterator range for binary values; before, a range
5. Since version 1.0.0.
6. Since version 1.0.0.
7. Since version 1.0.0. Fixed in version 3.13.0 to also check the iterator range for binary values; before, a range
that did not cover the whole value (such as `(end(), end())`) was accepted and the whole binary value was copied,
unlike the other primitive types.
8. Added in version 1.0.0.
9. Added in version 1.0.0.
8. Since version 1.0.0.
9. Since version 1.0.0.
+3 -2
View File
@@ -141,8 +141,9 @@ Logarithmic in the size of the JSON object.
## Version history
1. Added in version 3.11.0.
2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0. Support for keys
convertible to `std::string_view` added in version 3.13.0, consistently across the lookup functions.
2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0. Fixed in
version 3.13.0 to consistently accept `std::string_view`-convertible keys, as already supported by
[`operator[]`](operator[].md), [`at`](at.md), [`value`](value.md), and other lookup functions.
3. Added in version 3.7.0.
4. Deleted overloads for integral key types added in version 3.13.0 to reject such calls at compile time instead of
causing undefined behavior at runtime.
+3 -2
View File
@@ -92,7 +92,8 @@ Logarithmic in the size of the JSON object.
## Version history
1. Added in version 3.11.0.
2. Added in version 1.0.0. Changed to support comparable key types in version 3.11.0. Support for keys convertible to
`std::string_view` added in version 3.13.0, consistently across the lookup functions.
2. Added in version 1.0.0. Changed parameter `key` type to `KeyType&&` in version 3.11.0. Fixed in version 3.13.0 to
consistently accept `std::string_view`-convertible keys, as already supported by [`operator[]`](operator[].md),
[`at`](at.md), [`value`](value.md), and other lookup functions.
3. Deleted overload for integral key types added in version 3.13.0 to reject such calls at compile time instead of
causing undefined behavior at runtime.
+1 -1
View File
@@ -69,6 +69,6 @@ Logarithmic in the size of the container, O(log(`size()`)).
## Version history
- Added in version 2.0.8.
- Since version 2.0.8.
- Fixed in version 3.13.0: for [`ordered_json`](../ordered_json.md), the value could previously only be passed as an
rvalue; it can now also be passed as an lvalue or a `#!cpp const` lvalue, matching the behavior of `json`.
@@ -67,5 +67,5 @@ Amortized constant.
## Version history
- Added in version 2.0.8.
- Since version 2.0.8.
- Returns reference since 3.7.0.
+3 -2
View File
@@ -213,6 +213,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
1. Added in version 1.0.0. Added support for binary types in version 3.8.0.
2. Added in version 1.0.0. Added support for binary types in version 3.8.0.
3. Added in version 1.0.0.
4. Added in version 3.11.0. Support for keys convertible to `std::string_view` added in version 3.13.0, consistently
across the lookup functions.
4. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
already supported by [`operator[]`](operator[].md), [`at`](at.md), [`value`](value.md), and other lookup
functions.
5. Added in version 1.0.0.
+1 -1
View File
@@ -84,4 +84,4 @@ constructor.
## Version history
- Added in version 3.0.0.
- Since version 3.0.0.
+3 -2
View File
@@ -99,7 +99,8 @@ Logarithmic in the size of the JSON object.
## Version history
1. Added in version 3.11.0.
2. Added in version 1.0.0. Changed to support comparable types in version 3.11.0. Support for keys convertible to
`std::string_view` added in version 3.13.0, consistently across the lookup functions.
2. Added in version 1.0.0. Changed to support comparable types in version 3.11.0. Fixed in version 3.13.0 to
consistently accept `std::string_view`-convertible keys, as already supported by [`operator[]`](operator[].md),
[`at`](at.md), [`value`](value.md), and other lookup functions.
3. Deleted overloads for integral key types added in version 3.13.0 to reject such calls at compile time instead of
causing undefined behavior at runtime.
+1 -1
View File
@@ -57,4 +57,4 @@ Constant.
## Version history
- Added in version 1.0.0.
- Binary values are supported since version 3.8.0.
- Adjusted code to return reference to binary values in version 3.8.0.
+3 -3
View File
@@ -188,6 +188,6 @@ overload (3).
## Version history
1. Added in version 2.1.0.
2. Added in version 2.1.0. Extended to work with other specializations of `basic_json` in version 3.1.2.
3. Added in version 1.0.0.
1. Since version 2.1.0.
2. Since version 2.1.0. Extended to work with other specializations of `basic_json` in version 3.2.0.
3. Since version 1.0.0.
+1 -1
View File
@@ -76,5 +76,5 @@ Depends on the `json_serializer<ValueType>::from_json()` implementation.
## Version history
- Added in version 3.3.0.
- Since version 3.3.0.
- Added a `static_assert` with a clear message for `const` arguments in version 3.13.0.
-19
View File
@@ -44,22 +44,6 @@ are collected in [Template Parameter Requirements](../../features/types/template
- [**json**](../json.md) - default specialization
- [**ordered_json**](../ordered_json.md) - a specialization that maintains the insertion order of object keys
## Documents and views
Besides `basic_json`, the library offers a second way to hold a parsed JSON text: a
[`basic_json_document`](../basic_json_document/index.md), which owns or borrows the text and holds a flat index of the
values in it, and a [`basic_json_view`](../basic_json_view/index.md), a read-only handle to one value of such a document.
Both are defined in the header `<nlohmann/json_view.hpp>`; see
[Zero-copy JSON views](../../features/json_view.md) for the concept and the trade-offs.
- [**json_document**](../json_document.md) / [**ordered_json_document**](../ordered_json_document.md) - read-only
documents of the `basic_json` specialization they belong to
- [**json_editable_document**](../json_editable_document.md) /
[**ordered_json_editable_document**](../ordered_json_editable_document.md) - documents that can be modified in place
- [**json_view**](../json_view.md) / [**ordered_json_view**](../ordered_json_view.md) - views of a document
- [**json_editable_view**](../json_editable_view.md) /
[**ordered_json_editable_view**](../ordered_json_editable_view.md) - views of an editable document
## Iterator invalidation
All operations that add values to an **array** ([`push_back`](push_back.md) , [`operator+=`](operator+=.md),
@@ -359,9 +343,6 @@ Access to the JSON value
## See also
- [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc8259)
- [basic_json_document](../basic_json_document/index.md) / [basic_json_view](../basic_json_view/index.md) - parse a JSON
text into a flat index and read it through a view
- [Zero-copy JSON views](../../features/json_view.md) - when to use a document and a view instead of a `basic_json`
## Version history
@@ -75,4 +75,4 @@ classDiagram
## Version history
- Added in version 3.0.0.
- Since version 3.0.0.
+2 -2
View File
@@ -104,8 +104,8 @@ When iterating over an array, `key()` will return the index of the element as st
## Version history
- Added in version 3.1.0 as the replacement of the static function `iterator_wrapper`, which was available since
version 1.0.0 and is deprecated since version 3.1.0.
- Added `iterator_wrapper` in version 3.0.0.
- Added `items` and deprecated `iterator_wrapper` in version 3.1.0.
- Added structured binding support in version 3.5.0.
!!! warning "Deprecation"
@@ -51,4 +51,4 @@ deserializes. See [Template Parameter Requirements](../../features/types/templat
## Version history
- Added in version 2.1.0.
- Since version 2.0.0.
@@ -71,6 +71,6 @@ returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was
## Version history
- Added in version 3.1.0.
- Added in version 3.0.0.
- Fixed use of freed or relocated memory when `apply_patch` is `#!cpp *this` or refers to a value contained in
`#!cpp *this`, in version 3.13.0.
@@ -128,6 +128,6 @@ interpreted as `object_t::value_type` or `std::initializer_list<basic_json>`, se
## Version history
1. Added in version 1.0.0.
2. Added in version 1.0.0.
3. Added in version 2.0.0.
1. Since version 1.0.0.
2. Since version 1.0.0.
3. Since version 2.0.0.
@@ -284,10 +284,10 @@ Strong exception safety: if an exception occurs, the original value stays intact
1. Added in version 1.0.0. Fixed in version 3.13.0 to throw `#!cpp std::length_error` instead of emptying the array and
accessing it out of bounds when `idx` equals the maximum value of `size_type`. A missing index in the const version
is guarded by a runtime assertion since version 3.13.0.
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. The `T* key` overloads forward to
overload 3 since version 3.11.0.
3. Added in version 3.11.0. Support for keys convertible to `std::string_view` added in version 3.13.0, consistently
across the lookup functions.
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3)
in version 3.11.0.
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
already supported by [`at`](at.md), [`value`](value.md), [`find`](find.md), and other lookup functions.
4. Added in version 2.0.0. A missing array index in the const version is guarded by a runtime assertion since
version 3.13.0. Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) for a one-character array index that is not
@@ -89,6 +89,6 @@ Linear in the size of the JSON value.
## Version history
- Added in version 1.0.0.
- Since version 1.0.0.
- Macros `JSON_EXPLICIT`/[`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) added
in version 3.9.0.
@@ -75,4 +75,4 @@ classDiagram
## Version history
- Added in version 3.0.0.
- Since version 3.0.0.
@@ -76,4 +76,4 @@ classDiagram
## Version history
- Added in version 3.0.0.
- Since version 3.0.0.
+1 -34
View File
@@ -25,10 +25,6 @@ static basic_json parse(IteratorType first, SentinelType last,
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
the iterator type with `operator!=`.
Ill-formed UTF-16 and UTF-32 sequences are rejected: a lone surrogate, a high surrogate that is not followed by its
low surrogate, and a code point above `U+10FFFF` all yield a
[`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101).
## Template parameters
`InputType`
@@ -38,12 +34,9 @@ static basic_json parse(IteratorType first, SentinelType last,
- a `FILE` pointer (throws if null)
- a C-style array of characters
- a pointer to a null-terminated string of single byte characters (throws if null)
- a `std::string` or a `std::string_view` (C++17)
- a `std::string`
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
- wide characters (`wchar_t`, `char16_t`, `char32_t`), which are converted to UTF-8: a wide string object
(`std::wstring`, `std::u16string`, `std::u32string`) or an array (e.g. a wide string literal); a pointer to a
null-terminated wide string (e.g. `std::u16string::c_str()`) is not supported
`IteratorType`
: a compatible iterator type, for instance.
@@ -119,13 +112,6 @@ By default, a `'\0'` (NUL) byte anywhere in the input is treated as end of input
outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-bytes-in-the-input) for details and the
[`JSON_STRICT_NUL_HANDLING`](../macros/json_strict_nul_handling.md) macro to opt into rejecting it instead.
!!! tip "Parsing into a document instead of a value"
[`basic_json_document::parse`](../basic_json_document/parse.md) accepts the same inputs and the same options, but
keeps the result as a flat index of the parsed values instead of a tree of `basic_json` values. It is faster and uses
less memory when only parts of the document are read, and it also accepts a pointer to a null-terminated wide string,
which `parse()` does not. See [Zero-copy JSON views](../../features/json_view.md).
!!! tip "Performance"
Contiguous inputs (strings, string views, vectors, arrays, pointer ranges) are the fastest to parse. A
@@ -264,22 +250,6 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
--8<-- "examples/trailing_commas.output"
```
??? example "Example: parse from UTF-16, UTF-32, and wide strings"
The encoding is deduced from the character type of the input; `std::u16string` and `std::u32string` are interpreted
as UTF-16 and UTF-32, and `std::wstring` uses the platform's `wchar_t` width. String literals like `u"..."`,
`U"..."`, and `L"..."` work as well, as do iterators over wide characters.
```cpp
--8<-- "examples/parse__wide_string.cpp"
```
Output:
```json
--8<-- "examples/parse__wide_string.output"
```
## See also
- [accept](accept.md) - check if the input is valid JSON
@@ -310,9 +280,6 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
time).
- Parsing from a `FILE*` locks the file once instead of once per character in version 3.13.0
([`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md) restores `std::fgetc`).
- Ill-formed UTF-16 and UTF-32 input (a lone surrogate, a high surrogate that is not followed by its low surrogate, or
a code point above `U+10FFFF`) is rejected with `parse_error.101` in version 3.13.0; before that, some such
sequences were accepted or ended the input silently.
!!! warning "Deprecation"
@@ -84,4 +84,4 @@ or the end of file. This also holds true when reading a byte vector for binary f
## Version history
- Added in version 3.0.0.
- Since version 3.0.0.
+3 -3
View File
@@ -125,6 +125,6 @@ throws.
## Version history
1. Added in version 1.0.0.
2. Added in version 1.0.0.
3. Added in version 2.0.0.
1. Since version 1.0.0.
2. Since version 1.0.0.
3. Since version 2.0.0.
@@ -31,10 +31,6 @@ Read from input and generate SAX events
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
the iterator type with `operator!=`.
Ill-formed UTF-16 and UTF-32 sequences are rejected: a lone surrogate, a high surrogate that is not followed by its
low surrogate, and a code point above `U+10FFFF` all yield a
[`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101).
The SAX event lister must follow the interface of [`json_sax`](../json_sax/index.md).
## Template parameters
@@ -46,12 +42,8 @@ The SAX event lister must follow the interface of [`json_sax`](../json_sax/index
- a `FILE` pointer
- a C-style array of characters
- a pointer to a null-terminated string of single byte characters
- a `std::string` or a `std::string_view` (C++17)
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
- wide characters (`wchar_t`, `char16_t`, `char32_t`), which are converted to UTF-8: a wide string object
(`std::wstring`, `std::u16string`, `std::u32string`) or an array (e.g. a wide string literal); a pointer to a
null-terminated wide string (e.g. `std::u16string::c_str()`) is not supported
`IteratorType`
: a compatible iterator type for overload (2); a pair of character iterators whose `value_type` is an integral type
@@ -168,9 +160,6 @@ use the same file with stdio functions, but it must not wait for another thread
([`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md)).
- Parsing from a `FILE*` locks the file once instead of once per character in version 3.13.0
([`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md)).
- Ill-formed UTF-16 and UTF-32 input (a lone surrogate, a high surrogate that is not followed by its low surrogate, or
a code point above `U+10FFFF`) is rejected with `parse_error.101` in version 3.13.0; before that, some such
sequences were accepted or ended the input silently.
!!! warning "Deprecation"
+7 -7
View File
@@ -182,10 +182,10 @@ Constant.
## Version history
1. Added in version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
2. Added in version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
3. Added in version 1.0.0.
4. Added in version 1.0.0.
5. Added in version 1.0.0.
6. Added in version 3.8.0.
7. Added in version 3.8.0.
1. Since version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
2. Since version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
3. Since version 1.0.0.
4. Since version 1.0.0.
5. Since version 1.0.0.
6. Since version 3.8.0.
7. Since version 3.8.0.
@@ -124,3 +124,5 @@ Linear in the size of the JSON value `j`.
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled) throws `type_error.316`.
- Throws `type_error.321` for a discarded value since version 3.13.0; previously, a discarded value nested in an
array or object was silently skipped, producing invalid BJData.
- Writes unsigned integers wider than 64 bits as high-precision numbers since version 3.13.0; previously, they were
silently truncated to 64 bits.
@@ -76,4 +76,4 @@ classDiagram
## Version history
- Added in version 3.0.0.
- Since version 3.0.0.
+6 -3
View File
@@ -231,8 +231,11 @@ changes to any JSON value.
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version
3.11.0. Deleted overload for integral key types added in version 3.13.0 to reject such calls at compile time
instead of causing undefined behavior at runtime.
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2. Support for keys
convertible to `std::string_view` added in version 3.13.0, consistently across the lookup functions.
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0. Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109)
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2. Fixed in version 3.13.0
to consistently accept `std::string_view`-convertible keys, as already supported by
[`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md), and other lookup functions.
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0, including fixing an issue where resolving
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
`default_value`, as documented). Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109)
instead of returning `default_value` for a one-character array index that is not a digit (e.g., `/x`) in version
3.13.0, as it already did for longer ones.
@@ -9,8 +9,8 @@ class basic_json_document;
A parsed JSON text, held as a flat index of its values
([16 bytes per value](../../home/architecture.md#node-index-of-json-views)) instead of a tree of `BasicJsonType` values.
Strings and floating-point numbers stay in the source text; integers are converted while parsing, and strings that
contain escapes are decoded into one buffer owned by the document. [`basic_json_view`](../basic_json_view/index.md) is a read-only handle to one value of a
Strings and numbers stay in the source text; only strings that contain escapes are decoded, into one buffer owned by
the document. [`basic_json_view`](../basic_json_view/index.md) is a read-only handle to one value of a
`basic_json_document`; [`materialize()`](../basic_json_view/materialize.md) turns a subtree into the
`BasicJsonType` value that [`BasicJsonType::parse()`](../basic_json/parse.md) would have produced for it.
@@ -115,13 +115,6 @@ points apply to every edit:
[`source_offset()`](../basic_json_view/source_offset.md) of a value introduced by an edit is
`#!cpp static_cast<std::size_t>(-1)`, the same value it reports for a decoded string.
## See also
- [Zero-copy JSON views](../../features/json_view.md) - guide to documents and views
- [**basic_json_view**](../basic_json_view/index.md) - the non-owning handle to a value in a document
- [**json_document**](../json_document.md) and [**json_editable_document**](../json_editable_document.md) - the default specializations
- [**materialize**](../basic_json_view/materialize.md) - build a `basic_json` value from a view
## Version history
- Added in version 3.13.0.
@@ -21,19 +21,17 @@ static basic_json_document parse(IteratorType first, IteratorType last,
Both overloads accept the same JSON text as [`BasicJsonType::parse()`](../basic_json/parse.md), with the same
`ignore_comments`/`ignore_trailing_commas` options, but build a [`basic_json_document`](index.md) (a flat index into
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
Notes. Use [`parse_copy()`](parse_copy.md) to get an owned copy of a borrowable input
as well.
the input) instead of a tree of `BasicJsonType` values. They take the same inputs as `BasicJsonType::parse()`. Byte
inputs that stay alive can be borrowed; all others (streams, `#!cpp FILE*`, wide characters, 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.
## Template parameters
`InputType`
: A compatible input, for instance:
- a `#!cpp std::string`, a `#!cpp std::string_view` (C++17), or a C-style array of single-byte characters
- a `#!cpp std::string`, `#!cpp std::string_view`, or a C-style array of single-byte characters
- a pointer to a null-terminated string of single-byte characters (`#!cpp char`, `#!cpp signed char`,
`#!cpp unsigned char`, `#!cpp std::uint8_t`)
- a container for which `#!cpp obj.data()` and `#!cpp obj.size()` give contiguous single-byte access, e.g.
@@ -49,10 +47,6 @@ as well.
`#!cpp std::string::iterator`; the iterators of single-byte characters are borrowed or read like the byte inputs
above, those of wide characters are converted to UTF-8
Ill-formed UTF-16 and UTF-32 sequences are rejected: a lone surrogate, a high surrogate that is not followed by its low
surrogate, and a code point above `U+10FFFF` all yield a
[`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101).
## Parameters
`input` (in)
@@ -161,5 +155,3 @@ buffer of a given length, pass a pair of pointers: `#!cpp parse(ptr, ptr + len)`
## Version history
- Added in version 3.13.0.
- Ill-formed UTF-16 and UTF-32 input (a lone surrogate, a high surrogate that is not followed by its low surrogate, or
a code point above `U+10FFFF`) is rejected with `parse_error.101`.
@@ -143,13 +143,6 @@ still refers to it -- including ones taken before the change -- reads the new va
- [**source_offset**](source_offset.md) - byte offset of this value in the document's source text
## See also
- [Zero-copy JSON views](../../features/json_view.md) - guide to documents and views
- [**basic_json_document**](../basic_json_document/index.md) - the document that owns the parsed data
- [**json_view**](../json_view.md) and [**json_editable_view**](../json_editable_view.md) - the default specializations
- [**materialize**](materialize.md) - build a `basic_json` value from a view
## Version history
- Added in version 3.13.0.
@@ -51,4 +51,4 @@ byte_container_with_subtype(container_type&& container, subtype_type subtype);
## Version history
Added in version 3.8.0.
Since version 3.8.0.
@@ -39,4 +39,4 @@ Constant.
## Version history
Added in version 3.8.0.
Since version 3.8.0.
@@ -42,4 +42,4 @@ Constant.
## Version history
Added in version 3.8.0.
Since version 3.8.0.
@@ -29,14 +29,6 @@ specific naming scheme in order to override the binary type.
- [**has_subtype**](has_subtype.md) - return whether the value has a subtype
- [**clear_subtype**](clear_subtype.md) - clears the binary subtype
## See also
- [Binary values](../../features/binary_values.md) - how binary values and subtypes are handled
- [**binary**](../basic_json/binary.md) - create a binary array value
- [**get_binary**](../basic_json/get_binary.md) - get a reference to the stored binary value
- [**binary_t**](../basic_json/binary_t.md) - type for binary arrays
- [Binary formats](../../features/binary_formats/index.md) - formats that can store binary values
## Version history
- Added in version 3.8.0.
@@ -44,4 +44,4 @@ Constant.
## Version history
Added in version 3.8.0.
Since version 3.8.0.
+1 -1
View File
@@ -30,4 +30,4 @@ types.
## Version history
Added in version 1.0.0.
Since version 1.0.0.
+1 -1
View File
@@ -32,4 +32,4 @@ specialization.
## Version history
Added in version 3.13.0.
Since version 3.13.0.
@@ -40,4 +40,4 @@ parsing, without ever rewriting the source text -- see [Edits](basic_json_docume
## Version history
Added in version 3.13.0.
Since version 3.13.0.
+1 -1
View File
@@ -38,4 +38,4 @@ still referring to it seeing the change, see [Edits](basic_json_document/index.m
## Version history
Added in version 3.13.0.
Since version 3.13.0.
@@ -51,5 +51,5 @@ operator string_t() const
## Version history
- Added in version 2.0.0.
- Since version 2.0.0.
- Changed type to `string_t` and deprecated in version 3.11.0.
@@ -49,5 +49,5 @@ ptr == json_pointer(ptr.to_string());
## Version history
- Added in version 2.0.0.
- Since version 2.0.0.
- Changed return type to `string_t` in version 3.11.0.
-7
View File
@@ -59,13 +59,6 @@ leading `-` sign.
- [**start_object**](start_object.md) (_virtual_) - the beginning of an object was read
- [**string**](string.md) (_virtual_) - a string value was read
## See also
- [SAX interface](../../features/parsing/sax_interface.md) - guide to event-based parsing
- [**sax_parse**](../basic_json/sax_parse.md) - generate SAX events from an input
- [**parse**](../basic_json/parse.md) - DOM parsing, with optional [parser callbacks](../../features/parsing/parser_callbacks.md)
- [Parse exceptions](../../features/parsing/parse_exceptions.md)
## Version history
- Added in version 3.2.0.
+1 -1
View File
@@ -31,4 +31,4 @@ This type is a [`basic_json_view`](basic_json_view/index.md) of a value of a [`j
## Version history
Added in version 3.13.0.
Since version 3.13.0.
+1 -10
View File
@@ -137,13 +137,4 @@ header. See also the [macro overview page](../../features/macros.md).
- [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize/deserialize
a derived class; uses default values; uses custom names
- [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES**](nlohmann_define_type_with_names.md) - serialize a derived
class; uses custom names
## See also
- [Macros](../../features/macros.md) - guide to the supported macros
- [Runtime assertions](../../features/assertions.md)
- [Arbitrary type conversions](../../features/arbitrary_types.md) - using the `NLOHMANN_DEFINE_TYPE_*` macros
- [Enum conversion](../../features/enum_conversion.md) - using `NLOHMANN_JSON_SERIALIZE_ENUM`
- [The `nlohmann` namespace](../../features/namespace.md)
- [CMake integration](../../integration/cmake.md) - setting macros from the build system
class; uses custom names
+1 -1
View File
@@ -42,4 +42,4 @@ parsing an object of `n` keys costs O(n²) rather than O(n log n). See
## Version history
Added in version 3.9.0.
Since version 3.9.0.
@@ -35,4 +35,4 @@ of object keys, instead of sorting them like [`json_document`](json_document.md)
## Version history
Added in version 3.13.0.
Since version 3.13.0.
@@ -44,4 +44,4 @@ members [`set`](basic_json_document/set.md) added -- instead of sorting them lik
## Version history
Added in version 3.13.0.
Since version 3.13.0.
@@ -37,4 +37,4 @@ This type is a [`basic_json_view`](basic_json_view/index.md) of a value of an
## Version history
Added in version 3.13.0.
Since version 3.13.0.
+1 -1
View File
@@ -32,4 +32,4 @@ This type is a [`basic_json_view`](basic_json_view/index.md) of a value of an
## Version history
Added in version 3.13.0.
Since version 3.13.0.
+1 -1
View File
@@ -58,7 +58,7 @@ particular, a 3.x release does not:
- remove or rename a documented macro, CMake option, CMake target, or header, or change what a documented macro does.
Exceptions to these rules, for instance when fixing a bug requires changing the exception a function throws, are
documented in the [release notes](../home/releases/index.md).
documented in the [release notes](../home/releases.md).
The following are **not** part of the public API and may change in any release, including patch releases:
-29
View File
@@ -18,32 +18,3 @@
white-space: nowrap;
cursor: help;
}
/* byte layout tables of the binary formats */
.md-typeset .byte-layout td code {
white-space: pre-wrap;
}
.md-typeset .bl {
display: inline-block;
padding: 0 .25em;
border-radius: .2em;
font-family: var(--md-code-font-family);
font-size: .85em;
white-space: nowrap;
}
.md-typeset .bl-t {
background-color: rgba(66, 133, 244, .25);
box-shadow: inset 0 -.12em 0 rgba(66, 133, 244, .8);
}
.md-typeset .bl-l {
background-color: rgba(251, 140, 0, .25);
box-shadow: inset 0 -.12em 0 rgba(251, 140, 0, .8);
}
.md-typeset .bl-d {
background-color: rgba(67, 160, 71, .25);
box-shadow: inset 0 -.12em 0 rgba(67, 160, 71, .8);
}
@@ -1,18 +0,0 @@
#include <iostream>
#include <string>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// a valid JSON text, given as UTF-16
const std::u16string valid_text = u"{\"name\":\"\u00e9\"}";
// an invalid JSON text, given as UTF-16
const std::u16string invalid_text = u"{\"name\":\"\u00e9\",}";
std::cout << std::boolalpha
<< json::accept(valid_text) << ' '
<< json::accept(invalid_text) << '\n';
}
@@ -1 +0,0 @@
true false
@@ -0,0 +1,42 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
json j = json::parse(R"({"name": "Mary", "age": 42})");
// look up the key, then test the type: neither step throws
for (const char* key : {"name", "age", "city"})
{
const auto it = j.find(key);
if (it == j.end())
{
std::cout << key << ": missing\n";
}
else if (it->is_string())
{
std::cout << key << ": string \"" << it->get_ref<const std::string&>() << "\"\n";
}
else
{
std::cout << key << ": not a string, but " << it->type_name() << '\n';
}
}
// get_ptr returns a null pointer if the value has another type
const std::string* name = j["name"].get_ptr<const std::string*>();
const std::string* age = j["age"].get_ptr<const std::string*>();
std::cout << "get_ptr<string*>: name = " << (name != nullptr) << ", age = " << (age != nullptr) << '\n';
// value() is NOT exception-free: it throws if the key exists with a different type
try
{
std::cout << j.value("name", 0) << '\n';
}
catch (const json::type_error& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1,5 @@
name: string "Mary"
age: not a string, but number
city: missing
get_ptr<string*>: name = 1, age = 0
[json.exception.type_error.302] type must be number, but is string
@@ -0,0 +1,46 @@
#include <iostream>
#include <optional>
#include <string>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
struct person
{
std::string name;
int age;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, age)
// Compile this function with exceptions enabled and call it from code that does not use them.
std::optional<person> to_person(const json& j)
{
try
{
return j.get<person>();
}
catch (const json::exception&)
{
return std::nullopt;
}
}
int main()
{
const json good = {{"name", "Mary"}, {"age", 42}};
const json bad = {{"name", "Mary"}, {"age", "forty-two"}};
const json incomplete = {{"name", "Mary"}};
for (const json& j : {good, bad, incomplete})
{
if (const auto p = to_person(j))
{
std::cout << "person: " << p->name << ", " << p->age << '\n';
}
else
{
std::cout << "not a person: " << j << '\n';
}
}
}
@@ -0,0 +1,3 @@
person: Mary, 42
not a person: {"age":"forty-two","name":"Mary"}
not a person: {"name":"Mary"}
@@ -0,0 +1,28 @@
#include <cstdint>
#include <iostream>
#include <vector>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// None of the calls below throws, so this example also works with -fno-exceptions.
int main()
{
const std::string invalid = R"({"name": "Mary", "age": )";
// parse() with allow_exceptions = false returns a discarded value
json j = json::parse(invalid, nullptr, false);
std::cout << std::boolalpha << "parse: discarded = " << j.is_discarded() << '\n';
// accept() only tells whether the input is valid JSON
std::cout << "accept: " << json::accept(invalid) << '\n';
// the binary formats have the same parameter
const std::vector<std::uint8_t> truncated_cbor = {0x83, 0x01};
json c = json::from_cbor(truncated_cbor, true, false);
std::cout << "from_cbor: discarded = " << c.is_discarded() << '\n';
// valid input is parsed as usual
json valid = json::parse(R"({"name": "Mary"})", nullptr, false);
std::cout << "valid input: " << valid << '\n';
}
@@ -0,0 +1,4 @@
parse: discarded = true
accept: false
from_cbor: discarded = true
valid input: {"name":"Mary"}
@@ -1,27 +0,0 @@
#include <iostream>
#include <string>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// the same JSON text, given in different encodings
const std::string utf8 = "{\"name\":\"\u00e9\"}";
const std::u16string utf16 = u"{\"name\":\"\u00e9\"}";
const std::u32string utf32 = U"{\"name\":\"\u00e9\"}";
const std::wstring wide = L"{\"name\":\"\u00e9\"}";
// the encoding is deduced from the character type of the input, and all
// of them yield the same value
std::cout << json::parse(utf8) << '\n'
<< json::parse(utf16) << '\n'
<< json::parse(utf32) << '\n'
<< json::parse(wide) << '\n';
// a wide string literal works as well: u"..." is UTF-16, U"..." is UTF-32
std::cout << json::parse(u"[1, 2, 3]") << '\n';
// iterators over wide characters work as well
std::cout << json::parse(utf16.begin(), utf16.end()) << '\n';
}
@@ -1,6 +0,0 @@
{"name":"é"}
{"name":"é"}
{"name":"é"}
{"name":"é"}
[1,2,3]
{"name":"é"}
@@ -0,0 +1,42 @@
#include <iostream>
#include <utility>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// line and column (both starting at 1) of a byte index in a text
std::pair<std::size_t, std::size_t> line_column(const std::string& input, std::size_t byte)
{
std::size_t line = 1;
std::size_t column = 1;
for (std::size_t i = 0; i + 1 < byte && i < input.size(); ++i)
{
if (input[i] == '\n')
{
++line;
column = 1;
}
else
{
++column;
}
}
return {line, column};
}
int main()
{
const std::string input = "{\n \"a\": 1,\n \"b\": ]\n}";
try
{
const json j = json::parse(input);
std::cout << j << '\n';
}
catch (const json::parse_error& e)
{
const auto position = line_column(input, e.byte);
std::cout << e.what() << '\n';
std::cout << "byte " << e.byte << " = line " << position.first << ", column " << position.second << '\n';
}
}
@@ -0,0 +1,2 @@
[json.exception.parse_error.101] parse error at line 3, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
byte 20 = line 3, column 8
@@ -0,0 +1,46 @@
#define JSON_DIAGNOSTIC_POSITIONS 1
#include <iostream>
#include <utility>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// line and column (both starting at 1) of a byte index in a text
std::pair<std::size_t, std::size_t> line_column(const std::string& input, std::size_t byte)
{
std::size_t line = 1;
std::size_t column = 1;
for (std::size_t i = 0; i + 1 < byte && i < input.size(); ++i)
{
if (input[i] == '\n')
{
++line;
column = 1;
}
else
{
++column;
}
}
return {line, column};
}
int main()
{
const std::string input = "{\n \"name\": \"Mary\",\n \"age\": \"forty-two\"\n}";
const json j = json::parse(input); // the input is valid JSON ...
try
{
const int age = j["age"]; // ... but the value has the wrong type
std::cout << age << '\n';
}
catch (const json::exception& e)
{
std::cout << e.what() << '\n';
// start_pos() is a 0-based index into the input; the helper expects a 1-based byte index
const auto position = line_column(input, j["age"].start_pos() + 1);
std::cout << "the value starts at line " << position.first << ", column " << position.second << '\n';
}
}
@@ -0,0 +1,2 @@
[json.exception.type_error.302] (bytes 29-40) type must be number, but is string
the value starts at line 3, column 10
@@ -0,0 +1,46 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
std::string buffer;
// call for every chunk; returns true and sets `value` once the buffer holds one complete JSON value
bool push(const std::string& chunk, json& value)
{
buffer += chunk;
try
{
value = json::parse(buffer);
buffer.clear();
return true;
}
catch (const json::parse_error& e)
{
if (e.byte == buffer.size() + 1)
{
return false; // the input ends prematurely: wait for more data
}
throw; // a real syntax error
}
}
int main()
{
json value;
for (const std::string chunk : {"{\"na", "me\": \"Ma", "ry\", \"l", "ist\": [1, 2", ", 3]}"})
{
std::cout << "chunk " << chunk << " -> " << (push(chunk, value) ? "complete" : "incomplete") << '\n';
}
std::cout << value << '\n';
// a syntax error in the middle is not mistaken for missing data
try
{
push("[1, ]", value);
}
catch (const json::parse_error& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1,7 @@
chunk {"na -> incomplete
chunk me": "Ma -> incomplete
chunk ry", "l -> incomplete
chunk ist": [1, 2 -> incomplete
chunk , 3]} -> complete
{"list":[1,2,3],"name":"Mary"}
[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
@@ -0,0 +1,23 @@
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// a CBOR value followed by other data
const std::vector<std::uint8_t> cbor = json::to_cbor(json{1, 2, 3});
std::string data(cbor.begin(), cbor.end());
data += "TRAILING";
std::istringstream input(data);
json j = json::from_cbor(input, false); // strict = false: stop after the first value
std::cout << "value: " << j << '\n';
std::cout << "bytes used: " << input.tellg() << '\n';
std::string rest;
input >> rest;
std::cout << "remaining input: " << rest << '\n';
}
@@ -0,0 +1,3 @@
value: [1,2,3]
bytes used: 4
remaining input: TRAILING
@@ -0,0 +1,18 @@
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
std::istringstream input(R"({"a":1} [2,3] 4 "s")");
// check for the end of the stream before each read, because a read at the end throws
json j;
while (input >> std::ws && input.peek() != std::char_traits<char>::eof())
{
input >> j;
std::cout << j << '\n';
}
}
@@ -0,0 +1,4 @@
{"a":1}
[2,3]
4
"s"
@@ -0,0 +1,27 @@
#include <iostream>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
void handle(const json& record)
{
std::cout << "handling " << record << '\n';
}
int main()
{
std::istringstream file(R"([{"id": 1}, {"id": 2}, {"id": 3}])");
json result = json::parse(file, [](int depth, json::parse_event_t event, json & record)
{
if (depth == 1 && event == json::parse_event_t::object_end)
{
handle(record);
return false; // discard the record
}
return true;
});
std::cout << "result: " << result << '\n';
}
@@ -0,0 +1,4 @@
handling {"id":1}
handling {"id":2}
handling {"id":3}
result: []
@@ -0,0 +1,81 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
struct find_id : nlohmann::json_sax<json>
{
bool next_is_id = false;
json::number_unsigned_t id = 0;
bool key(std::string& name) override
{
next_is_id = (name == "id");
return true;
}
bool number_unsigned(json::number_unsigned_t value) override
{
if (next_is_id)
{
id = value;
return false; // found: stop parsing
}
return true;
}
bool null() override
{
return true;
}
bool boolean(bool /*val*/) override
{
return true;
}
bool number_integer(json::number_integer_t /*val*/) override
{
return true;
}
bool number_float(json::number_float_t /*val*/, const std::string& /*s*/) override
{
return true;
}
bool string(std::string& /*val*/) override
{
return true;
}
bool binary(json::binary_t& /*val*/) override
{
return true;
}
bool start_object(std::size_t /*elements*/) override
{
return true;
}
bool end_object() override
{
return true;
}
bool start_array(std::size_t /*elements*/) override
{
return true;
}
bool end_array() override
{
return true;
}
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& /*ex*/) override
{
return false;
}
};
int main()
{
find_id handler;
const bool completed = json::sax_parse(R"({"x": [1, 2, 3], "id": 42, "rest": [4, 5, 6]})", &handler);
std::cout << std::boolalpha;
std::cout << "parse completed: " << completed << '\n';
std::cout << "id: " << handler.id << '\n';
}
@@ -0,0 +1,2 @@
parse completed: false
id: 42
@@ -0,0 +1,56 @@
#include <chrono>
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace nlohmann
{
template <typename Rep, typename Period>
struct adl_serializer<std::chrono::duration<Rep, Period>>
{
static void to_json(json& j, const std::chrono::duration<Rep, Period>& d)
{
j = d.count();
}
static void from_json(const json& j, std::chrono::duration<Rep, Period>& d)
{
d = std::chrono::duration<Rep, Period>(j.get<Rep>());
}
};
template <typename Duration>
struct adl_serializer<std::chrono::time_point<std::chrono::system_clock, Duration>>
{
static void to_json(json& j, const std::chrono::time_point<std::chrono::system_clock, Duration>& t)
{
j = t.time_since_epoch();
}
static void from_json(const json& j, std::chrono::time_point<std::chrono::system_clock, Duration>& t)
{
t = std::chrono::time_point<std::chrono::system_clock, Duration>(j.get<Duration>());
}
};
} // namespace nlohmann
int main()
{
using namespace std::chrono;
std::cout << std::boolalpha;
// the unit is not part of the JSON value
const json timeout = milliseconds(1500);
std::cout << "duration: " << timeout << '\n';
std::cout << "as milliseconds: " << timeout.get<milliseconds>().count() << '\n';
// a system_clock time point is the time since the Unix epoch
const time_point<system_clock, milliseconds> t(milliseconds(1700000000123));
const json stamp = t;
std::cout << "time point: " << stamp << '\n';
const auto back = stamp.get<time_point<system_clock, milliseconds>>();
std::cout << "round trip: " << (back == t) << '\n';
}
@@ -0,0 +1,4 @@
duration: 1500
as milliseconds: 1500
time point: 1700000000123
round trip: true
@@ -0,0 +1,99 @@
#include <iostream>
#include <memory>
#include <stdexcept>
#include <vector>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
struct shape
{
virtual ~shape() = default;
virtual json serialize() const = 0;
};
struct circle : shape
{
double radius;
explicit circle(double r) : radius(r) {}
json serialize() const override
{
return {{"type", "circle"}, {"radius", radius}};
}
};
struct rectangle : shape
{
double width;
double height;
rectangle(double w, double h) : width(w), height(h) {}
json serialize() const override
{
return {{"type", "rectangle"}, {"width", width}, {"height", height}};
}
};
namespace nlohmann
{
template <>
struct adl_serializer<std::unique_ptr<shape>>
{
static void to_json(json& j, const std::unique_ptr<shape>& p)
{
j = p ? p->serialize() : json(nullptr);
}
static void from_json(const json& j, std::unique_ptr<shape>& p)
{
if (j.is_null())
{
p.reset();
return;
}
const auto& type = j.at("type").get_ref<const std::string&>();
if (type == "circle")
{
p = std::make_unique<circle>(j.at("radius").get<double>());
}
else if (type == "rectangle")
{
p = std::make_unique<rectangle>(j.at("width").get<double>(), j.at("height").get<double>());
}
else
{
throw std::invalid_argument("unknown shape type: " + type);
}
}
};
} // namespace nlohmann
int main()
{
std::vector<std::unique_ptr<shape>> shapes;
shapes.push_back(std::make_unique<circle>(1.5));
shapes.push_back(std::make_unique<rectangle>(2, 3));
const json j = shapes;
std::cout << j << '\n';
// reading creates objects of the derived types
const auto back = j.get<std::vector<std::unique_ptr<shape>>>();
std::cout << std::boolalpha;
std::cout << "first is a circle: " << (dynamic_cast<circle*>(back[0].get()) != nullptr) << '\n';
std::cout << "second is a rectangle: " << (dynamic_cast<rectangle*>(back[1].get()) != nullptr) << '\n';
// an unknown type tag is reported
try
{
json{{"type", "star"}}.get<std::unique_ptr<shape>>();
}
catch (const std::invalid_argument& e)
{
std::cout << e.what() << '\n';
}
}
@@ -0,0 +1,4 @@
[{"radius":1.5,"type":"circle"},{"height":3.0,"type":"rectangle","width":2.0}]
first is a circle: true
second is a rectangle: true
unknown shape type: star
@@ -0,0 +1,90 @@
#include <iostream>
#include <memory>
#include <vector>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace nlohmann
{
template <typename T>
struct adl_serializer<std::shared_ptr<T>>
{
static void to_json(json& j, const std::shared_ptr<T>& p)
{
if (p)
{
j = *p;
}
else
{
j = nullptr;
}
}
static void from_json(const json& j, std::shared_ptr<T>& p)
{
if (j.is_null())
{
p = nullptr;
}
else
{
p = std::make_shared<T>(j.get<typename std::remove_const<T>::type>());
}
}
};
template <typename T>
struct adl_serializer<std::unique_ptr<T>>
{
static void to_json(json& j, const std::unique_ptr<T>& p)
{
if (p)
{
j = *p;
}
else
{
j = nullptr;
}
}
static void from_json(const json& j, std::unique_ptr<T>& p)
{
if (j.is_null())
{
p = nullptr;
}
else
{
p = std::make_unique<T>(j.get<T>());
}
}
};
} // namespace nlohmann
struct point
{
int x;
int y;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(point, x, y)
int main()
{
// an empty pointer is written as null
const std::vector<std::shared_ptr<point>> points = {std::make_shared<point>(point{1, 2}), nullptr};
const json j = points;
std::cout << j << '\n';
// reading allocates new objects
const auto back = j.get<std::vector<std::shared_ptr<point>>>();
std::cout << back[0]->x << ", " << back[0]->y << ", " << (back[1] == nullptr) << '\n';
// pointers to const and unique_ptr work as well
const auto const_ptr = j[0].get<std::shared_ptr<const point>>();
const auto unique = j[0].get<std::unique_ptr<point>>();
std::cout << const_ptr->y << ", " << unique->x << '\n';
}
@@ -0,0 +1,3 @@
[{"x":1,"y":2},null]
1, 2, 1
2, 1
@@ -0,0 +1,63 @@
#include <iostream>
#include <stdexcept>
#include <variant>
#include <vector>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace geo
{
struct circ
{
double radius;
};
struct rect
{
double width;
double height;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(circ, radius)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(rect, width, height)
using figure = std::variant<circ, rect>;
void to_json(json& j, const figure& f)
{
std::visit([&j](const auto & alternative)
{
j = alternative;
}, f);
j["type"] = std::holds_alternative<circ>(f) ? "circ" : "rect";
}
void from_json(const json& j, figure& f)
{
const auto& type = j.at("type").get_ref<const std::string&>();
if (type == "circ")
{
f = j.get<circ>();
}
else if (type == "rect")
{
f = j.get<rect>();
}
else
{
throw std::invalid_argument("unknown figure type: " + type);
}
}
} // namespace geo
int main()
{
const std::vector<geo::figure> figures = {geo::circ{2}, geo::rect{3, 4}};
const json j = figures;
std::cout << j << '\n';
const auto back = j.get<std::vector<geo::figure>>();
std::cout << "alternatives read back: " << back[0].index() << ", " << back[1].index() << '\n';
}
@@ -0,0 +1,2 @@
[{"radius":2.0,"type":"circ"},{"height":4.0,"type":"rect","width":3.0}]
alternatives read back: 0, 1
@@ -409,6 +409,32 @@ namespace nlohmann {
}
```
## Why isn't my `to_json` or `from_json` found?
The library calls `to_json` and `from_json` without qualification, so the compiler finds them by
[argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) in the namespace of the type, or in the
namespaces of its template arguments. The usual reasons for a function that is "not found" are:
- **The type is an alias of a standard type.** After `#!cpp using Hash = std::array<std::uint8_t, 6>;` the type
*is* `std::array<std::uint8_t, 6>`, which lives in namespace `std`. A `to_json(json&, const Hash&)` in your namespace
is never selected. Either give the type its own identity, for example `#!cpp struct Hash : std::array<std::uint8_t, 6> {};`
(the function is then found in `Hash`'s namespace), or specialize
[`adl_serializer<Hash>`](#how-do-i-convert-third-party-types).
- **The function is in the wrong namespace.** It must be in the namespace of the type (a global type needs a global
function), not in the namespace of the code that calls the conversion. Specializations of `adl_serializer` belong in
namespace `nlohmann`.
- **It is declared too late.** A conversion can only use what has been declared when it is instantiated. If
`#!cpp json j = std::vector<third_party::string>{...};` appears before the `adl_serializer` specialization, the
compiler reports an error such as "explicit specialization of `adl_serializer<...>` after instantiation". Put the
specialization in a small header that every file includes **before** it uses the type with `json`.
- **It is a template.** For `template <class T> struct box`, write `template <class T> void to_json(json&, const box<T>&)`,
not an overload for one `T`.
- **It worked by accident.** Some versions found `to_json` overloads in `nlohmann::detail` through argument-dependent
lookup of the base class of `basic_json`. Do not rely on this; it is not part of the interface.
For smart pointers, class hierarchies, `std::variant`, and `std::chrono`, see
[Recipes for common types](type_recipes.md).
## Why can't I convert to/from `std::any`?
`std::any` is intentionally excluded from `get<T>()`/generic conversion support, so `get<std::any>()` and
@@ -505,6 +531,7 @@ struct bad_serializer
## See also
- [Recipes for common types](type_recipes.md) - smart pointers, class hierarchies, `std::variant`, and `std::chrono`
- [Converting values](conversions.md) - the general overview of `get`/`get_to` and implicit conversions
- [Specializing enum conversion](enum_conversion.md) - map enums to JSON strings instead of integers
- [Supported macros](macros.md) - reference for `NLOHMANN_DEFINE_TYPE_*` and related macros
+3 -1
View File
@@ -7,7 +7,9 @@ detect bugs in client code.
## Switch off runtime assertions
Runtime assertions can be switched off by defining the preprocessor macro `NDEBUG` (see the
[documentation of assert](https://en.cppreference.com/w/cpp/error/assert)) which is the default for release builds.
[documentation of assert](https://en.cppreference.com/w/cpp/error/assert)) which is the default for release builds. Without `NDEBUG`, the assertions are compiled in and contain the name of the source
file (`__FILE__`); see [notes for builds and distribution](../integration/index.md#notes-for-builds-and-distribution)
if that path must not end up in your binaries.
## Change assertion behavior
@@ -190,41 +190,6 @@ The library uses the following mapping from JSON values types to BJData types ac
--8<-- "examples/to_bjdata.output"
```
### Byte layout
Consider the following JSON value (shown formatted for readability):
```json
{
"id": 300,
"name": "json",
"pi": 3.14,
"tags": [
"a",
"b"
]
}
```
`to_bjdata` encodes it to 51 bytes (shown in hexadecimal; the encoding contains no whitespace). The colors mark the role of each byte: <span class="bl bl-t">type/marker</span> <span class="bl bl-l">length/count/size</span> <span class="bl bl-d">data</span>.
<div class="byte-layout" markdown="0"><table>
<thead><tr><th>JSON</th><th>Bytes</th><th>Meaning</th></tr></thead><tbody>
<tr><td><code>{</code></td><td><span class="bl bl-t">7B</span></td><td>object start (<code>{</code>)</td></tr>
<tr><td><code>&quot;id&quot;: 300,</code></td><td><span class="bl bl-l">69 02</span> <span class="bl bl-d">69 64</span> <span class="bl bl-t">49</span> <span class="bl bl-d">2C 01</span></td><td>key: length 2 as int8 (<code>i</code>), then UTF-8 bytes; value: int16 (<code>I</code>), little-endian</td></tr>
<tr><td><code>&quot;name&quot;: &quot;json&quot;,</code></td><td><span class="bl bl-l">69 04</span> <span class="bl bl-d">6E 61 6D 65</span> <span class="bl bl-t">53</span> <span class="bl bl-l">69 04</span> <span class="bl bl-d">6A 73 6F 6E</span></td><td>key: length 4; value: string (<code>S</code>), length 4 as int8, UTF-8 bytes</td></tr>
<tr><td><code>&quot;pi&quot;: 3.14,</code></td><td><span class="bl bl-l">69 02</span> <span class="bl bl-d">70 69</span> <span class="bl bl-t">44</span> <span class="bl bl-d">1F 85 EB 51 B8 1E 09 40</span></td><td>key: length 2; value: float64 (<code>D</code>), little-endian</td></tr>
<tr><td><code>&quot;tags&quot;: [</code></td><td><span class="bl bl-l">69 04</span> <span class="bl bl-d">74 61 67 73</span> <span class="bl bl-t">5B</span></td><td>key: length 4; value: array start (<code>[</code>)</td></tr>
<tr><td><code>&quot;a&quot;,</code></td><td><span class="bl bl-t">53</span> <span class="bl bl-l">69 01</span> <span class="bl bl-d">61</span></td><td>string, length 1</td></tr>
<tr><td><code>&quot;b&quot;</code></td><td><span class="bl bl-t">53</span> <span class="bl bl-l">69 01</span> <span class="bl bl-d">62</span></td><td>string, length 1</td></tr>
<tr><td><code>]</code></td><td><span class="bl bl-t">5D</span></td><td>array end (<code>]</code>)</td></tr>
<tr><td><code>}</code></td><td><span class="bl bl-t">7D</span></td><td>object end (<code>}</code>)</td></tr>
</tbody></table></div>
## Deserialization
The library maps BJData types to JSON value types as follows:
@@ -105,41 +105,6 @@ serialized as 0x81 0x65 0xFF, but `[1,2,3,4,"e"]` as 0x85 0x91 0x92 0x93 0x94 0x
--8<-- "examples/to_bon8.output"
```
### Byte layout
Consider the following JSON value (shown formatted for readability):
```json
{
"id": 300,
"name": "json",
"pi": 3.14,
"tags": [
"a",
"b"
]
}
```
`to_bon8` encodes it to 35 bytes (shown in hexadecimal; the encoding contains no whitespace). The colors mark the role of each byte: <span class="bl bl-t">type/marker</span> <span class="bl bl-l">length/count/size</span> <span class="bl bl-d">data</span>.
<div class="byte-layout" markdown="0"><table>
<thead><tr><th>JSON</th><th>Bytes</th><th>Meaning</th></tr></thead><tbody>
<tr><td><code>{</code></td><td><span class="bl bl-t">8A</span></td><td>object with 4 members</td></tr>
<tr><td><code>&quot;id&quot;: 300,</code></td><td><span class="bl bl-d">69 64</span> <span class="bl bl-t">C4</span> <span class="bl bl-d">04</span></td><td>key: UTF-8 bytes; the string ends at the next byte, which cannot continue a UTF-8 character; value: 2-byte positive integer (lead byte, then a byte below 0x80)</td></tr>
<tr><td><code>&quot;name&quot;: &quot;json&quot;,</code></td><td><span class="bl bl-d">6E 61 6D 65</span> <span class="bl bl-l">FF</span> <span class="bl bl-d">6A 73 6F 6E</span> <span class="bl bl-l">FF</span></td><td>key: UTF-8 bytes; 0xFF terminates the string as another string follows; value: UTF-8 bytes; terminated as a string key follows</td></tr>
<tr><td><code>&quot;pi&quot;: 3.14,</code></td><td><span class="bl bl-d">70 69</span> <span class="bl bl-t">8F</span> <span class="bl bl-d">40 09 1E B8 51 EB 85 1F</span></td><td>key: UTF-8 bytes; value: binary64 (IEEE 754, big-endian); its marker also ends <code>&quot;pi&quot;</code></td></tr>
<tr><td><code>&quot;tags&quot;: [</code></td><td><span class="bl bl-d">74 61 67 73</span> <span class="bl bl-t">82</span></td><td>key: UTF-8 bytes; value: array with 2 elements; its marker also ends <code>&quot;tags&quot;</code></td></tr>
<tr><td><code>&quot;a&quot;,</code></td><td><span class="bl bl-d">61</span> <span class="bl bl-l">FF</span></td><td>UTF-8 bytes; terminated as a string follows</td></tr>
<tr><td><code>&quot;b&quot;</code></td><td><span class="bl bl-d">62</span> <span class="bl bl-l">FF</span></td><td>UTF-8 bytes; terminated as nothing follows</td></tr>
<tr><td><code>]</code></td><td></td><td>no end marker: the element count was given up front</td></tr>
<tr><td><code>}</code></td><td></td><td>no end marker: the member count was given up front</td></tr>
</tbody></table></div>
## Deserialization
The library maps BON8 types to JSON value types as follows:
@@ -61,41 +61,6 @@ The library uses the following mapping from JSON values types to BSON types:
```
### Byte layout
Consider the following JSON value (shown formatted for readability):
```json
{
"id": 300,
"name": "json",
"pi": 3.14,
"tags": [
"a",
"b"
]
}
```
`to_bson` encodes it to 69 bytes (shown in hexadecimal; the encoding contains no whitespace). The colors mark the role of each byte: <span class="bl bl-t">type/marker</span> <span class="bl bl-l">length/count/size</span> <span class="bl bl-d">data</span>.
<div class="byte-layout" markdown="0"><table>
<thead><tr><th>JSON</th><th>Bytes</th><th>Meaning</th></tr></thead><tbody>
<tr><td><code>{</code></td><td><span class="bl bl-l">45 00 00 00</span></td><td>document size: 69 bytes (int32, little-endian)</td></tr>
<tr><td><code>&quot;id&quot;: 300,</code></td><td><span class="bl bl-t">10</span> <span class="bl bl-d">69 64 00</span> <span class="bl bl-d">2C 01 00 00</span></td><td>int32 element; key as NUL-terminated string; value (little-endian)</td></tr>
<tr><td><code>&quot;name&quot;: &quot;json&quot;,</code></td><td><span class="bl bl-t">02</span> <span class="bl bl-d">6E 61 6D 65 00</span> <span class="bl bl-l">05 00 00 00</span> <span class="bl bl-d">6A 73 6F 6E 00</span></td><td>string element; key; length incl. NUL (int32); NUL-terminated UTF-8 bytes</td></tr>
<tr><td><code>&quot;pi&quot;: 3.14,</code></td><td><span class="bl bl-t">01</span> <span class="bl bl-d">70 69 00</span> <span class="bl bl-d">1F 85 EB 51 B8 1E 09 40</span></td><td>double element; key; value (little-endian)</td></tr>
<tr><td><code>&quot;tags&quot;: [</code></td><td><span class="bl bl-t">04</span> <span class="bl bl-d">74 61 67 73 00</span> <span class="bl bl-l">17 00 00 00</span></td><td>array element; key; embedded document of 23 bytes (keys are the indices)</td></tr>
<tr><td><code>&quot;a&quot;,</code></td><td><span class="bl bl-t">02</span> <span class="bl bl-d">30 00</span> <span class="bl bl-l">02 00 00 00</span> <span class="bl bl-d">61 00</span></td><td>string element; key <code>&quot;0&quot;</code>; length 2; <code>a</code> + NUL</td></tr>
<tr><td><code>&quot;b&quot;</code></td><td><span class="bl bl-t">02</span> <span class="bl bl-d">31 00</span> <span class="bl bl-l">02 00 00 00</span> <span class="bl bl-d">62 00</span></td><td>string element; key <code>&quot;1&quot;</code>; length 2; <code>b</code> + NUL</td></tr>
<tr><td><code>]</code></td><td><span class="bl bl-t">00</span></td><td>end of the array document</td></tr>
<tr><td><code>}</code></td><td><span class="bl bl-t">00</span></td><td>end of the document</td></tr>
</tbody></table></div>
## Deserialization
The library maps BSON record types to JSON value types as follows:
@@ -110,41 +110,6 @@ see "binary" cells in the table above.
--8<-- "examples/to_cbor.output"
```
### Byte layout
Consider the following JSON value (shown formatted for readability):
```json
{
"id": 300,
"name": "json",
"pi": 3.14,
"tags": [
"a",
"b"
]
}
```
`to_cbor` encodes it to 39 bytes (shown in hexadecimal; the encoding contains no whitespace). The colors mark the role of each byte: <span class="bl bl-t">type/marker</span> <span class="bl bl-l">length/count/size</span> <span class="bl bl-d">data</span>.
<div class="byte-layout" markdown="0"><table>
<thead><tr><th>JSON</th><th>Bytes</th><th>Meaning</th></tr></thead><tbody>
<tr><td><code>{</code></td><td><span class="bl bl-t">A4</span></td><td>map with 4 key/value pairs</td></tr>
<tr><td><code>&quot;id&quot;: 300,</code></td><td><span class="bl bl-t">62</span> <span class="bl bl-d">69 64</span> <span class="bl bl-t">19</span> <span class="bl bl-d">01 2C</span></td><td>key: text string of length 2, then its UTF-8 bytes; value: unsigned integer, 2 bytes follow (big-endian)</td></tr>
<tr><td><code>&quot;name&quot;: &quot;json&quot;,</code></td><td><span class="bl bl-t">64</span> <span class="bl bl-d">6E 61 6D 65</span> <span class="bl bl-t">64</span> <span class="bl bl-d">6A 73 6F 6E</span></td><td>key: text string of length 4; value: text string of length 4</td></tr>
<tr><td><code>&quot;pi&quot;: 3.14,</code></td><td><span class="bl bl-t">62</span> <span class="bl bl-d">70 69</span> <span class="bl bl-t">FB</span> <span class="bl bl-d">40 09 1E B8 51 EB 85 1F</span></td><td>key: text string of length 2; value: double-precision float (IEEE 754, big-endian)</td></tr>
<tr><td><code>&quot;tags&quot;: [</code></td><td><span class="bl bl-t">64</span> <span class="bl bl-d">74 61 67 73</span> <span class="bl bl-t">82</span></td><td>key: text string of length 4; value: array with 2 elements</td></tr>
<tr><td><code>&quot;a&quot;,</code></td><td><span class="bl bl-t">61</span> <span class="bl bl-d">61</span></td><td>text string of length 1</td></tr>
<tr><td><code>&quot;b&quot;</code></td><td><span class="bl bl-t">61</span> <span class="bl bl-d">62</span></td><td>text string of length 1</td></tr>
<tr><td><code>]</code></td><td></td><td>no end marker: the element count was given up front</td></tr>
<tr><td><code>}</code></td><td></td><td>no end marker: the member count was given up front</td></tr>
</tbody></table></div>
## Deserialization
The library maps CBOR types to JSON value types as follows:
@@ -45,19 +45,12 @@ 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+type) | 58.6 % | 92.1 % | 86.5 % | 97.4 % |
| BON8 | **50.5 %** | **83.8 %** | **63.5 %** | **87.5 %** |
| BON8 | 50.5 % | 83.8 % | 63.5 % | 87.5 % |
| 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 % |
| CBOR | 50.5 % | 86.3 % | 68.4 % | 88.0 % |
| MessagePack | 50.5 % | 86.0 % | 68.5 % | 87.9 % |
| UBJSON | 53.2 % | 91.3 % | 78.2 % | 96.6 % |
| UBJSON (size) | 58.6 % | 92.3 % | 86.8 % | 97.4 % |
| UBJSON (size+type) | 55.9 % | 92.3 % | 85.0 % | 95.0 % |
Sizes compared to minified JSON value; the smallest size per file is printed in bold.
## See also
- [Binary values](../binary_values.md) - binary values and subtypes
- [**to_cbor**](../../api/basic_json/to_cbor.md) / [**from_cbor**](../../api/basic_json/from_cbor.md), [**to_msgpack**](../../api/basic_json/to_msgpack.md) / [**from_msgpack**](../../api/basic_json/from_msgpack.md), [**to_bson**](../../api/basic_json/to_bson.md) / [**from_bson**](../../api/basic_json/from_bson.md), [**to_ubjson**](../../api/basic_json/to_ubjson.md) / [**from_ubjson**](../../api/basic_json/from_ubjson.md), [**to_bjdata**](../../api/basic_json/to_bjdata.md) / [**from_bjdata**](../../api/basic_json/from_bjdata.md), [**to_bon8**](../../api/basic_json/to_bon8.md) / [**from_bon8**](../../api/basic_json/from_bon8.md) - the conversion functions
- [Parsing untrusted input](../parsing/untrusted_input.md)
- [SAX interface](../parsing/sax_interface.md) - decode binary formats without building a value
Sizes compared to minified JSON value.
@@ -91,41 +91,6 @@ specification:
--8<-- "examples/to_msgpack.output"
```
### Byte layout
Consider the following JSON value (shown formatted for readability):
```json
{
"id": 300,
"name": "json",
"pi": 3.14,
"tags": [
"a",
"b"
]
}
```
`to_msgpack` encodes it to 39 bytes (shown in hexadecimal; the encoding contains no whitespace). The colors mark the role of each byte: <span class="bl bl-t">type/marker</span> <span class="bl bl-l">length/count/size</span> <span class="bl bl-d">data</span>.
<div class="byte-layout" markdown="0"><table>
<thead><tr><th>JSON</th><th>Bytes</th><th>Meaning</th></tr></thead><tbody>
<tr><td><code>{</code></td><td><span class="bl bl-t">84</span></td><td>map with 4 key/value pairs</td></tr>
<tr><td><code>&quot;id&quot;: 300,</code></td><td><span class="bl bl-t">A2</span> <span class="bl bl-d">69 64</span> <span class="bl bl-t">CD</span> <span class="bl bl-d">01 2C</span></td><td>key: fixstr of length 2, then its UTF-8 bytes; value: uint 16 (big-endian)</td></tr>
<tr><td><code>&quot;name&quot;: &quot;json&quot;,</code></td><td><span class="bl bl-t">A4</span> <span class="bl bl-d">6E 61 6D 65</span> <span class="bl bl-t">A4</span> <span class="bl bl-d">6A 73 6F 6E</span></td><td>key: fixstr of length 4; value: fixstr of length 4</td></tr>
<tr><td><code>&quot;pi&quot;: 3.14,</code></td><td><span class="bl bl-t">A2</span> <span class="bl bl-d">70 69</span> <span class="bl bl-t">CB</span> <span class="bl bl-d">40 09 1E B8 51 EB 85 1F</span></td><td>key: fixstr of length 2; value: float 64 (IEEE 754, big-endian)</td></tr>
<tr><td><code>&quot;tags&quot;: [</code></td><td><span class="bl bl-t">A4</span> <span class="bl bl-d">74 61 67 73</span> <span class="bl bl-t">92</span></td><td>key: fixstr of length 4; value: fixarray with 2 elements</td></tr>
<tr><td><code>&quot;a&quot;,</code></td><td><span class="bl bl-t">A1</span> <span class="bl bl-d">61</span></td><td>fixstr of length 1</td></tr>
<tr><td><code>&quot;b&quot;</code></td><td><span class="bl bl-t">A1</span> <span class="bl bl-d">62</span></td><td>fixstr of length 1</td></tr>
<tr><td><code>]</code></td><td></td><td>no end marker: the element count was given up front</td></tr>
<tr><td><code>}</code></td><td></td><td>no end marker: the member count was given up front</td></tr>
</tbody></table></div>
## Deserialization
The library maps MessagePack types to JSON value types as follows:
@@ -103,41 +103,6 @@ The library uses the following mapping from JSON values types to UBJSON types ac
--8<-- "examples/to_ubjson.output"
```
### Byte layout
Consider the following JSON value (shown formatted for readability):
```json
{
"id": 300,
"name": "json",
"pi": 3.14,
"tags": [
"a",
"b"
]
}
```
`to_ubjson` encodes it to 51 bytes (shown in hexadecimal; the encoding contains no whitespace). The colors mark the role of each byte: <span class="bl bl-t">type/marker</span> <span class="bl bl-l">length/count/size</span> <span class="bl bl-d">data</span>.
<div class="byte-layout" markdown="0"><table>
<thead><tr><th>JSON</th><th>Bytes</th><th>Meaning</th></tr></thead><tbody>
<tr><td><code>{</code></td><td><span class="bl bl-t">7B</span></td><td>object start (<code>{</code>)</td></tr>
<tr><td><code>&quot;id&quot;: 300,</code></td><td><span class="bl bl-l">69 02</span> <span class="bl bl-d">69 64</span> <span class="bl bl-t">49</span> <span class="bl bl-d">01 2C</span></td><td>key: length 2 as int8 (<code>i</code>), then UTF-8 bytes; value: int16 (<code>I</code>), big-endian</td></tr>
<tr><td><code>&quot;name&quot;: &quot;json&quot;,</code></td><td><span class="bl bl-l">69 04</span> <span class="bl bl-d">6E 61 6D 65</span> <span class="bl bl-t">53</span> <span class="bl bl-l">69 04</span> <span class="bl bl-d">6A 73 6F 6E</span></td><td>key: length 4; value: string (<code>S</code>), length 4 as int8, UTF-8 bytes</td></tr>
<tr><td><code>&quot;pi&quot;: 3.14,</code></td><td><span class="bl bl-l">69 02</span> <span class="bl bl-d">70 69</span> <span class="bl bl-t">44</span> <span class="bl bl-d">40 09 1E B8 51 EB 85 1F</span></td><td>key: length 2; value: float64 (<code>D</code>), big-endian</td></tr>
<tr><td><code>&quot;tags&quot;: [</code></td><td><span class="bl bl-l">69 04</span> <span class="bl bl-d">74 61 67 73</span> <span class="bl bl-t">5B</span></td><td>key: length 4; value: array start (<code>[</code>)</td></tr>
<tr><td><code>&quot;a&quot;,</code></td><td><span class="bl bl-t">53</span> <span class="bl bl-l">69 01</span> <span class="bl bl-d">61</span></td><td>string, length 1</td></tr>
<tr><td><code>&quot;b&quot;</code></td><td><span class="bl bl-t">53</span> <span class="bl bl-l">69 01</span> <span class="bl bl-d">62</span></td><td>string, length 1</td></tr>
<tr><td><code>]</code></td><td><span class="bl bl-t">5D</span></td><td>array end (<code>]</code>)</td></tr>
<tr><td><code>}</code></td><td><span class="bl bl-t">7D</span></td><td>object end (<code>}</code>)</td></tr>
</tbody></table></div>
## Deserialization
The library maps UBJSON types to JSON value types as follows:
+23 -13
View File
@@ -38,18 +38,6 @@ which avoids repeating it:
--8<-- "examples/get_to.output"
```
!!! info "Getting values out of a document or a view"
A [view](../api/basic_json_view/index.md) offers the same `get<T>()` conversion. For the built-in types (booleans,
numbers, strings, `#!cpp std::vector`, `#!cpp std::map`, ...) it reads the value straight from the document's
index, without building a `basic_json` value first; user-defined types with a `from_json()` are converted from a
`basic_json` value, see the [list](../api/basic_json_view/get.md). Two conversions never copy at all:
[`get_string()`](../api/basic_json_view/get_string.md) returns a string as a view into the source text, and
[`number_token()`](../api/basic_json_view/number_token.md) returns a number exactly as it was written. Every other
type is obtained from a subtree that is built on demand with
[`materialize()`](../api/basic_json_view/materialize.md). See
[Zero-copy JSON views](json_view.md#getting-values-out-without-copying).
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:
@@ -124,6 +112,29 @@ Implicit conversions are convenient but can be surprising (for example, in overl
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 "`auto` copies the JSON value; it does not convert it"
The type of `#!cpp j["name"]` is `json`, not the C++ type of the value inside. `#!cpp auto` therefore deduces
`json`:
```cpp
json j = {{"name", "Mary"}, {"age", 42}};
auto name = j["name"]; // json: a copy of the value; prints as "Mary" (with quotes)
std::string s1 = j["name"]; // std::string: implicit conversion
auto s2 = j["name"].get<std::string>(); // std::string: explicit conversion
auto& age = j["age"]; // json&: a reference, no copy
age = 43; // changes j
```
This is also why `#!cpp std::cout << j["name"]` prints the quotes (see
[getting a string without quotes](#getting-values-out)), and why a `json` value cannot be passed to `printf`: the
argument is not an `int` or a `char*`, and a compiler either rejects passing it through `...` (Clang does) or
compiles it and prints garbage. Convert first: `#!cpp std::printf("%d", j["age"].get<int>());`.
Prefer `get<T>()` over `auto` when you want the C++ value, and `auto&` or `const auto&` when you want to avoid a
copy of a large value.
!!! warning "Conversions do not range-check numbers"
Just like C++ itself, the `get` family performs numeric conversions without range checks — retrieving a
@@ -246,4 +257,3 @@ The conversions above are built in for standard types. To make the same syntax w
- [`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
- [Zero-copy JSON views](json_view.md) - get values out of a document or a view
+20 -4
View File
@@ -1,9 +1,7 @@
# 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). A JSON text can also be parsed into a
[document](../api/basic_json_document/index.md) and read through a [view](../api/basic_json_view/index.md) instead of
into a value; see [Zero-copy JSON views](json_view.md).
instead, see [parsing](parsing/index.md).
## From C++ values
@@ -61,6 +59,25 @@ with a string as the first element is treated as an object, everything else as a
[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.
### What does this produce?
The following table shows how some common spellings are interpreted. When in doubt, use `#!cpp json::array()`,
`#!cpp json::object()`, or the `#!cpp json(value)` form with parentheses.
| code | result | note |
|-------------------------------------------------|------------------------------|----------------------------------------------|
| `#!cpp json j = {};` / `#!cpp json j{};` | `#!json null` | use `json::object()` or `json::array()` |
| `#!cpp json j = json::object();` | `#!json {}` | |
| `#!cpp json j = json::array();` | `#!json []` | |
| `#!cpp json j(true);` | `#!json true` | parentheses create the value itself |
| `#!cpp json j = {true};` | `#!json [true]` | braces create a one-element array (`#!cpp json j{true};` depends on the compiler, see the [FAQ](../home/faq.md#brace-initialization-yields-arrays)) |
| `#!cpp json j = {{"a", 1}};` | `#!json {"a":1}` | all elements are `[string, value]` pairs: object |
| `#!cpp json j = {{"a", 1}, {"b"}};` | `#!json [["a",1],["b"]]` | one element is not a pair: array |
| `#!cpp json j = {{"a", 1}, 2};` | `#!json [["a",1],2]` | a plain value among pairs: array |
| `#!cpp json j = {{"a", 1, 2}};` | `#!json [["a",1,2]]` | a three-element list is not a pair: array |
| `#!cpp json j = "{\"a\":1}";` | `#!json "{\"a\":1}"` | a string **value**; it is not parsed |
| `#!cpp json j = json::parse("{\"a\":1}");` | `#!json {"a":1}` | parse text with `parse` or `_json` |
## Building incrementally
A value can also be built up piece by piece. Accessing a non-existing object key or array index with
@@ -103,4 +120,3 @@ string `#!json "42"`.
- [`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
- [Zero-copy JSON views](json_view.md) - create a document and a view from JSON text instead of a value
Loaded 100 of 168 files, more files were not shown because too many files have changed in this diff. Show more