mirror of
https://github.com/nlohmann/json.git
synced 2026-10-10 16:37:14 +00:00
Merge branch 'json-view/19-edit-set' into json-view/21-images
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
64 files changed
+2746
-897
No files matched your search
@@ -23,10 +23,10 @@ type to use.
|
||||
## Template parameters
|
||||
|
||||
`NumberFloatType`
|
||||
: the type to store floating-point numbers. The parser converts `#!cpp float`, `#!cpp double`, and a
|
||||
`#!cpp long double` that is IEEE 754 binary64 itself and other `#!cpp long double` formats with
|
||||
`#!cpp std::from_chars` or `#!cpp std::strtold`, and serialization falls back to `#!cpp std::snprintf`, so the
|
||||
type must be `#!cpp float`, `#!cpp double`, or `#!cpp long double`. The
|
||||
: the type to store floating-point numbers. The type must be `#!cpp float`, `#!cpp double`, or
|
||||
`#!cpp long double`. The parser converts `#!cpp float`, `#!cpp double`, and a `#!cpp long double` that is IEEE 754
|
||||
binary64 itself. It converts other `#!cpp long double` formats with `#!cpp std::from_chars` where available, or
|
||||
with `#!cpp std::strtold` otherwise. Serialization falls back to `#!cpp std::snprintf`. The
|
||||
[binary formats](../../features/binary_formats/index.md) additionally require `#!cpp float` or `#!cpp double`,
|
||||
because they have no encoding for `#!cpp long double`. See
|
||||
[Template Parameter Requirements](../../features/types/template_parameters.md#numberfloattype).
|
||||
|
||||
@@ -43,6 +43,11 @@ input's own copy (for inputs that are always read into a buffer) throws.
|
||||
|
||||
Linear in the length of the input.
|
||||
|
||||
## Notes
|
||||
|
||||
An integer argument that is not a `#!cpp bool` where the flags are expected, such as `#!cpp accept(ptr, len)`, does not
|
||||
compile; see [`parse`](parse.md#notes).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -86,8 +86,8 @@ view of a *different* document (overloads 1-2 only; overload 3 always starts fro
|
||||
|
||||
!!! info "Duplicate keys"
|
||||
|
||||
Overload 1. removes *every* member with `key`, not just the first -- unlike [`set`](set.md), which assigns the
|
||||
first occurrence and drops the rest. This is why it returns a count rather than a single view: there may be
|
||||
Overload 1. removes *every* member with `key`, not just the last one that lookups find -- unlike [`set`](set.md),
|
||||
which assigns that member and drops the rest. This is why it returns a count rather than a single view: there may be
|
||||
more than one member removed, or none.
|
||||
|
||||
Like [`set`](set.md) and [`push_back`](push_back.md), `erase` never moves an element's *value*: a view still
|
||||
|
||||
@@ -19,24 +19,33 @@ static basic_json_document parse(IteratorType first, IteratorType last,
|
||||
1. Deserialize from a compatible input, borrowing or owning it depending on its value category and type (see Notes).
|
||||
2. Deserialize from a pair of input iterators.
|
||||
|
||||
Both overloads accept exactly what [`BasicJsonType::parse()`](../basic_json/parse.md) accepts, with the same
|
||||
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.
|
||||
the input) instead of a tree of `BasicJsonType` values. The input must be byte-oriented (see the template parameters
|
||||
below): not every input type of `BasicJsonType::parse()` is supported.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`InputType`
|
||||
: A compatible input, for instance:
|
||||
: A byte-oriented input, one of:
|
||||
|
||||
- a `#!cpp std::string`, `#!cpp std::string_view`, or a C-style array of characters
|
||||
- a pointer to a null-terminated string 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.
|
||||
`#!cpp std::vector<char>` or `#!cpp std::vector<std::uint8_t>`
|
||||
- an `#!cpp std::istream` object, or anything else [`BasicJsonType::parse()`](../basic_json/parse.md) accepts
|
||||
- an `#!cpp std::istream` object
|
||||
- a wide string object (`#!cpp std::wstring`, `#!cpp std::u16string`, `#!cpp std::u32string`), which is converted
|
||||
to UTF-8
|
||||
|
||||
Other inputs are not supported: a `#!cpp FILE*`, and pointers to or arrays of wide characters (`#!cpp wchar_t`,
|
||||
`#!cpp char16_t`, `#!cpp char32_t`) are rejected at compile time by a `#!cpp static_assert`. (Use
|
||||
[`BasicJsonType::parse()`](../basic_json/parse.md) for these.)
|
||||
|
||||
`IteratorType`
|
||||
: a compatible iterator type, for instance a pair of pointers such as `ptr` and `ptr + len`, or a pair of
|
||||
`#!cpp std::string::iterator`
|
||||
: an input iterator type, for instance a pair of pointers such as `ptr` and `ptr + len`, or a pair of
|
||||
`#!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
|
||||
|
||||
## Parameters
|
||||
|
||||
@@ -70,8 +79,8 @@ discarded; see [`is_discarded`](is_discarded.md).
|
||||
Throws the same exception [`BasicJsonType::parse()`](../basic_json/parse.md) throws for the same input and options --
|
||||
the same exception id, message, and position -- because on a failing input the library's own parser is run on the
|
||||
same bytes to produce the diagnostic. Additionally throws
|
||||
[`out_of_range.416`](../../home/exceptions.md#jsonexceptionout_of_range416) if the input is 4 GiB or larger, a size
|
||||
[`BasicJsonType::parse()`](../basic_json/parse.md) does not reject.
|
||||
[`out_of_range.416`](../../home/exceptions.md#jsonexceptionout_of_range416) if the input is 4294967280 bytes (4 GiB
|
||||
minus 16 bytes) or larger, a size [`BasicJsonType::parse()`](../basic_json/parse.md) does not reject.
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -84,8 +93,8 @@ Linear in the length of the input.
|
||||
| `input` | ownership |
|
||||
|--------------------------------------------------------------------------------------|--------------------------------------------------------------|
|
||||
| lvalue byte container (`std::string`, `std::vector<char>`, ...), `std::string_view`, C string, character array | **borrowed** -- `input` must outlive the document |
|
||||
| rvalue `#!cpp std::string` | **owned**, moved in without a copy |
|
||||
| rvalue byte container other than `#!cpp std::string` | **owned**, copied |
|
||||
| non-const rvalue `#!cpp std::string` | **owned**, moved in without a copy |
|
||||
| other rvalue byte container (including a `#!cpp const` rvalue `#!cpp std::string`) | **owned**, copied |
|
||||
| stream, wide string, or anything else read through the general input adapter | **owned**, read into a buffer (a stream is read to its end) |
|
||||
|
||||
For overload (2), a pair of pointers to single-byte integers (e.g. `#!cpp const char*`, `#!cpp std::uint8_t*`) is
|
||||
@@ -100,6 +109,12 @@ See [`owns_source`](owns_source.md) to check which happened after a call, and th
|
||||
**Numbers.** As for [`BasicJsonType::parse()`](../basic_json/parse.md), an integer literal too large for the 64-bit
|
||||
integer type becomes a floating-point value.
|
||||
|
||||
**No lengths.** An integer argument that is not a `#!cpp bool` where the flags are expected -- for example
|
||||
`#!cpp parse(ptr, len)` -- does not compile (the overload is deleted). Such a call would convert `len` to
|
||||
`allow_exceptions` and read `ptr` as a null-terminated string, past the end of a buffer that has none. To parse a
|
||||
buffer of a given length, pass a pair of pointers: `#!cpp parse(ptr, ptr + len)`. The same holds for
|
||||
[`parse_copy`](parse_copy.md), [`accept`](accept.md), and [`read`](read.md).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: (1) borrowed vs. owned input, and errors identical to `BasicJsonType::parse()`"
|
||||
|
||||
@@ -51,6 +51,9 @@ Linear in the length of the input.
|
||||
only differs in that the input is always copied rather than sometimes borrowed. Prefer [`parse()`](parse.md) when the
|
||||
input's lifetime already covers the document's, since it avoids the copy for borrowed inputs.
|
||||
|
||||
An integer argument that is not a `#!cpp bool` where the flags are expected, such as `#!cpp parse_copy(ptr, len)`, does not
|
||||
compile; see [`parse`](parse.md#notes).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -54,6 +54,9 @@ page at a time, and every page costs a page fault the first time it is written.
|
||||
a 55 MB document into a reused document took about 40 % less time than parsing it into a fresh one. Programs that parse
|
||||
many documents of similar size should therefore keep one document and call `read()`.
|
||||
|
||||
An integer argument that is not a `#!cpp bool` where the flags are expected, such as `#!cpp read(ptr, len)`, does not
|
||||
compile; see [`parse`](parse.md#notes).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
# <small>nlohmann::basic_json_document::</small>root
|
||||
|
||||
```cpp
|
||||
view_type root() const noexcept;
|
||||
// (1)
|
||||
view_type root() const& noexcept;
|
||||
|
||||
// (2)
|
||||
view_type root() const&& = delete;
|
||||
```
|
||||
|
||||
Returns a view of the root value of the document.
|
||||
1. Returns a view of the root value of the document.
|
||||
2. Deleted: the view of a temporary document would dangle.
|
||||
|
||||
## Return value
|
||||
|
||||
@@ -21,6 +26,16 @@ Constant.
|
||||
|
||||
## Notes
|
||||
|
||||
**Lifetime.** A view refers into the document, so the document must outlive it. `root()` can therefore only be called
|
||||
on a document that has a name (an lvalue); calling it on a temporary does not compile:
|
||||
|
||||
```cpp
|
||||
auto v = json_document::parse(text).root(); // error: the document is destroyed at the end of the statement
|
||||
|
||||
auto doc = json_document::parse(text); // OK: keep the document alive
|
||||
auto v = doc.root();
|
||||
```
|
||||
|
||||
`root()` is a cheap handle into the document's index, not a copy of anything; call it as often as needed. The
|
||||
returned view is valid under the same conditions as any other view of the document -- see
|
||||
[Object inspection](../basic_json_view/index.md) -- in particular, it is invalidated by the next
|
||||
|
||||
@@ -23,7 +23,8 @@ has `set`; calling it on a read-only `basic_json_document` fails to compile (`#!
|
||||
|
||||
1. Replaces the value `target` refers to with `value`.
|
||||
2. Sets the member `key` of the object `object` to `value`: assigns it if `object` already has a member with this
|
||||
key -- the first one, should the key occur more than once, and the later duplicates are then dropped (see the
|
||||
key -- the last one, should the key occur more than once (the member
|
||||
[`operator[]`](../basic_json_view/operator%5B%5D.md) returns), and the other duplicates are then dropped (see the
|
||||
[Notes](#notes) below) -- or appends a new member at the end otherwise. A [null](../basic_json_view/is_null.md)
|
||||
`object` first becomes an empty object.
|
||||
3. Assigns `value` to the element at index `idx` of the array `array`, which must already exist (`#!cpp idx <
|
||||
@@ -31,7 +32,10 @@ has `set`; calling it on a read-only `basic_json_document` fails to compile (`#!
|
||||
4. Sets the value the JSON pointer `ptr` refers to, relative to [`root()`](root.md), to `value`. The *parent* of the
|
||||
target must already exist: an object member is set as in 2. (added if it does not exist yet), an array element is
|
||||
assigned as in 3., and a last reference token of `#!cpp "-"`, or equal to the size of the array, appends `value`
|
||||
instead, exactly as [`push_back`](push_back.md) would. An empty `ptr` sets [`root()`](root.md) itself, as in 1.
|
||||
instead, exactly as [`push_back`](push_back.md) would. A [null](../basic_json_view/is_null.md) parent becomes what
|
||||
[`basic_json::operator[]`](../basic_json/operator%5B%5D.md) with a JSON pointer makes of it: an array if the last
|
||||
reference token is `#!cpp "-"` or consists of digits only (for an index beyond 0, the array is first filled with
|
||||
null values up to that index), an object otherwise. An empty `ptr` sets [`root()`](root.md) itself, as in 1.
|
||||
|
||||
In every overload, `value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any*
|
||||
document -- read-only or editable, and it does not have to be `target`'s/`object`'s/`array`'s own document -- which
|
||||
@@ -85,7 +89,8 @@ invalid argument, or `#!cpp std::bad_alloc`) leaves the document completely unch
|
||||
for the encoding that is not reclaimed. A failure of a later allocation -- while an edited array or object switches
|
||||
from its parsed layout to a growable block, see [Notes](#notes) -- can still leave a partial effect, such as a
|
||||
[null](../basic_json_view/is_null.md) `object`/`array` argument already turned into an empty object/array even
|
||||
though `value` itself was not linked in.
|
||||
though `value` itself was not linked in. Likewise, a failure of `value` in 4. leaves a null parent that is set with an
|
||||
index beyond 0 already filled with the null values before the index.
|
||||
|
||||
## Exceptions
|
||||
|
||||
@@ -111,8 +116,10 @@ though `value` itself was not linked in.
|
||||
[`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) (a leading `#!cpp '0'`),
|
||||
[`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) (not a number),
|
||||
[`out_of_range.410`](../../home/exceptions.md#jsonexceptionout_of_range410) (too large for `size_type`), or
|
||||
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) (an empty token). Also throws what 1.
|
||||
throws for `value`.
|
||||
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) (an empty token); the same errors are
|
||||
thrown for a null parent and a token of digits (the parent is not changed then), and
|
||||
[`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if the index is 4294967295 or more.
|
||||
Also throws what 1. throws for `value`.
|
||||
|
||||
Every overload also throws [`type_error.319`](../../home/exceptions.md#jsonexceptiontype_error319) if `value` is (or
|
||||
contains) a binary value -- `BasicJsonType` can hold one, but a `json_document` cannot -- and
|
||||
@@ -125,24 +132,28 @@ document") if `target`/`object`/`array` is a [discarded](../basic_json_view/is_d
|
||||
1. Linear in the size of `value` (encoding it into the document's storage): constant for a scalar, linear in the
|
||||
number of nested values for an array or object. If `target` is itself an array or object that spans more than one
|
||||
node in its parent's original, unedited layout, and `value` is a scalar, replacing it additionally costs time
|
||||
linear in the number of elements of that parent, the *first* time -- see [Notes](#notes).
|
||||
linear in the size of the document, the *first* time (the parent of `target` is looked up from
|
||||
[`root()`](root.md), and then switches to links) -- see [Notes](#notes). Once the parent has links, `target` is
|
||||
replaced in constant time: setting every element of a large array one after the other is linear overall. To avoid
|
||||
the lookup altogether, use 3. (or 2. for an object), which know the parent.
|
||||
2. Linear in the number of members of `object`, to find an existing member with `key`, plus the complexity of 1. for
|
||||
`value`.
|
||||
3. Constant, plus the complexity of 1. for `value`.
|
||||
4. Linear in the number of reference tokens of `ptr` and, for each token, in the number of members of the object at
|
||||
that level or the index into the array (as [`at`](../basic_json_view/at.md)), plus the complexity of 2. or 3. for
|
||||
the last token.
|
||||
the last token; for a null parent and an index, linear in the index.
|
||||
|
||||
## Notes
|
||||
|
||||
!!! info "Duplicate keys"
|
||||
|
||||
If `object` already has more than one member with `key` (2.), the *first* one is assigned `value` and every
|
||||
later member with the same key is removed -- so that a lookup, an iteration, and
|
||||
[`materialize()`](../basic_json_view/materialize.md) of `object` afterward all agree on a single value for
|
||||
`key`, the same way [`operator[]`](../basic_json_view/operator%5B%5D.md) already picks the first occurrence of a
|
||||
duplicate key for reading. See the [Notes on duplicate keys](../basic_json_view/operator%5B%5D.md#notes) of
|
||||
`operator[]`.
|
||||
If `object` already has more than one member with `key` (2.), `value` is assigned to the *last* one -- the member
|
||||
[`operator[]`](../basic_json_view/operator%5B%5D.md), [`at`](../basic_json_view/at.md), and
|
||||
[`find`](../basic_json_view/find.md) return for reading, so that a view taken from `object["key"]` before the call
|
||||
shows `value` afterward -- and every other member with the same key is removed. The key stays at the
|
||||
position of its *first* occurrence, where [`materialize()`](../basic_json_view/materialize.md) puts it as well. A
|
||||
lookup, an iteration, and `materialize()` of `object` afterward therefore all agree on a single member for `key`. See the
|
||||
[Notes on duplicate keys](../basic_json_view/operator%5B%5D.md#notes) of `operator[]`.
|
||||
|
||||
Setting a member (2.) or an element (3., through 4.) of an array or object whose elements have not been edited
|
||||
before switches it from its parsed layout to a growable block holding links to its elements; a later
|
||||
|
||||
@@ -8,15 +8,18 @@ basic_json_view at(const string_t& key) const;
|
||||
|
||||
// (2)
|
||||
basic_json_view at(size_type idx) const;
|
||||
basic_json_view at(int idx) const;
|
||||
template<typename IntegerType>
|
||||
basic_json_view at(IntegerType idx) const;
|
||||
|
||||
// (3)
|
||||
basic_json_view at(const json_pointer& ptr) const;
|
||||
```
|
||||
|
||||
1. Returns the value of the object member with key `key` -- the first one, should the key occur more than once (see
|
||||
1. Returns the value of the object member with key `key` -- the last one, should the key occur more than once (see
|
||||
[Notes on duplicate keys](operator[].md#notes)).
|
||||
2. Returns the array element at index `idx`.
|
||||
2. Returns the array element at index `idx`. The template accepts every integer type except `#!cpp bool` and
|
||||
`#!cpp std::size_t` and forwards to the `size_type` overload, as for [`operator[]`](operator[].md); a negative
|
||||
`idx` is out of range.
|
||||
3. Returns the value a JSON pointer `ptr` refers to, starting at this value.
|
||||
|
||||
## Parameters
|
||||
@@ -32,7 +35,7 @@ basic_json_view at(const json_pointer& ptr) const;
|
||||
|
||||
## Return value
|
||||
|
||||
1. the value of the first member with key `key`
|
||||
1. the value of the last member with key `key`
|
||||
2. the element at index `idx`
|
||||
3. the value `ptr` resolves to, starting at this value
|
||||
|
||||
@@ -72,8 +75,8 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics
|
||||
## Complexity
|
||||
|
||||
1. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after
|
||||
another, in document order, stopping at the first match. Each comparison first checks the key's length --
|
||||
already known from the index, without reading the key bytes -- before comparing its content.
|
||||
another, in document order, scanning all of them, since the last match is wanted. Each comparison first checks the
|
||||
key's length -- already known from the index, without reading the key bytes -- before comparing its content.
|
||||
Objects with 128 or more members get a hash index while parsing, so that a lookup in them takes constant time
|
||||
on average.
|
||||
2. Linear in `idx`: elements are skipped one at a time from the first one, since they are not a fixed size in the
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
basic_json_view() noexcept = default;
|
||||
```
|
||||
|
||||
Creates an invalid (discarded) view: [`type()`](type.md) is `#!cpp value_t::discarded`,
|
||||
[`is_discarded()`](is_discarded.md) is `#!cpp true`, and `#!cpp explicit operator bool()` is `#!cpp false`.
|
||||
Creates an invalid (discarded) view: [`type()`](type.md) is `#!cpp value_t::discarded` and
|
||||
[`is_discarded()`](is_discarded.md) is `#!cpp true`.
|
||||
|
||||
This is the only constructor a caller can use directly. Every other view is obtained from a
|
||||
[`basic_json_document`](../basic_json_document/index.md), via [`root()`](../basic_json_document/root.md) or by
|
||||
@@ -44,7 +44,6 @@ placeholder for "no value yet" and later be assigned a real view.
|
||||
## See also
|
||||
|
||||
- [is_discarded](is_discarded.md) - return whether the view is invalid
|
||||
- [operator bool](operator_bool.md) - return whether the view refers to a value
|
||||
- [root](../basic_json_document/root.md) - the view of a document's root value
|
||||
|
||||
## Version history
|
||||
|
||||
@@ -24,7 +24,7 @@ Constant.
|
||||
|
||||
For an object, iteration visits **every** member, including all occurrences of a duplicate key -- unlike
|
||||
[`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md), [`contains`](contains.md), and [`count`](count.md),
|
||||
which all resolve to the *first* member with a given key. See the
|
||||
which all resolve to the *last* member with a given key. See the
|
||||
[Notes on duplicate keys](operator[].md#notes) of `operator[]`.
|
||||
|
||||
Because objects are iterated in document order rather than sorted by key, the order seen here can differ from what
|
||||
|
||||
@@ -33,8 +33,8 @@ No-throw guarantee: this function never throws exceptions.
|
||||
## Complexity
|
||||
|
||||
1. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after
|
||||
another, in document order, stopping at the first match. Each comparison first checks the key's length -- already
|
||||
known from the index, without reading the key bytes -- before comparing its content.
|
||||
another, in document order, scanning all of them, since the last match is wanted. Each comparison first checks the
|
||||
key's length -- already known from the index, without reading the key bytes -- before comparing its content.
|
||||
Objects with 128 or more members get a hash index while parsing, so that a lookup in them takes constant time
|
||||
on average.
|
||||
2. Linear in the number of reference tokens of `ptr` and, for each token, in the number of members of the object at
|
||||
|
||||
@@ -23,9 +23,9 @@ No-throw guarantee: this function never throws exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after
|
||||
another, in document order, stopping at the first match. Each comparison first checks the key's length -- already
|
||||
known from the index, without reading the key bytes -- before comparing its content.
|
||||
Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after another,
|
||||
in document order, scanning all of them, since the last match is wanted. Each comparison first checks the key's length
|
||||
-- already known from the index, without reading the key bytes -- before comparing its content.
|
||||
Objects with 128 or more members get a hash index while parsing, so that a lookup in them takes constant time on
|
||||
average.
|
||||
|
||||
@@ -38,7 +38,7 @@ Unlike [`BasicJsonType::count()`](../basic_json/count.md), whose return value ca
|
||||
an `ObjectType` that allows multiple entries per key, `count()` here never does: it is exactly
|
||||
[`contains()`](contains.md) as `#!cpp 0`/`#!cpp 1`. This holds even if the source text has a duplicate key -- see the
|
||||
[Notes on duplicate keys](operator[].md#notes) of `operator[]` -- because a `#!cpp count() > 1` result would require
|
||||
counting every member with a matching key, not just finding the first one.
|
||||
counting every member with a matching key (the lookup functions resolve to the *last* one).
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ iterator find(const char* key) const;
|
||||
iterator find(const string_t& key) const;
|
||||
```
|
||||
|
||||
Finds a member with key `key` -- the first one, should the key occur more than once (see
|
||||
Finds a member with key `key` -- the last one, should the key occur more than once (see
|
||||
[Notes on duplicate keys](operator[].md#notes)). If the value is not an object, or no member has this key,
|
||||
[`end()`](end.md) is returned.
|
||||
|
||||
@@ -25,9 +25,9 @@ No-throw guarantee: this function never throws exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after
|
||||
another, in document order, stopping at the first match. Each comparison first checks the key's length -- already
|
||||
known from the index, without reading the key bytes -- before comparing its content.
|
||||
Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after another,
|
||||
in document order, scanning all of them, since the last match is wanted. Each comparison first checks the key's length
|
||||
-- already known from the index, without reading the key bytes -- before comparing its content.
|
||||
Objects with 128 or more members get a hash index while parsing, so that a lookup in them takes constant time on
|
||||
average.
|
||||
|
||||
|
||||
@@ -87,9 +87,9 @@ exception thrown while converting through `materialize()` (the last bullet) is d
|
||||
!!! info "Duplicate keys"
|
||||
|
||||
`#!cpp std::map`/`#!cpp std::unordered_map` conversions keep the *last* value of a repeated key, like
|
||||
[`materialize()`](materialize.md) and [`BasicJsonType::parse()`](../basic_json/parse.md) do. This is the opposite
|
||||
of [`operator[]`](operator[].md)/[`at`](at.md)/[`find`](find.md)/[`contains`](contains.md), which resolve to the
|
||||
*first* occurrence (see the [Notes on duplicate keys](operator[].md#notes)).
|
||||
[`materialize()`](materialize.md) and [`BasicJsonType::parse()`](../basic_json/parse.md) do. This is the member
|
||||
[`operator[]`](operator[].md)/[`at`](at.md)/[`find`](find.md)/[`contains`](contains.md) resolve to, too (see the
|
||||
[Notes on duplicate keys](operator[].md#notes)).
|
||||
|
||||
!!! info "No pointers, references, or implicit conversion"
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@ still refers to it -- including ones taken before the change -- reads the new va
|
||||
- [**is_primitive**](is_primitive.md) - return whether the type is primitive
|
||||
- [**is_structured**](is_structured.md) - return whether the type is structured
|
||||
- [**is_discarded**](is_discarded.md) - return whether the view is invalid
|
||||
- [**operator bool**](operator_bool.md) - return whether the view refers to a value
|
||||
|
||||
### Element access
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ view (see [(constructor)](basic_json_view.md)), and for [`root()`](../basic_json
|
||||
that is itself [discarded](../basic_json_document/is_discarded.md) -- in particular, the root of a failed
|
||||
[`parse()`](../basic_json_document/parse.md) with `allow_exceptions` set to `#!cpp false`.
|
||||
|
||||
A discarded view is also what [`operator[]`](operator[].md) returns for a missing key, an index out of range, or a
|
||||
JSON pointer that cannot be resolved, and for any access on a view that is itself discarded (so a chain such as
|
||||
`#!cpp v["a"]["b"]` is safe). [`at`](at.md) throws instead.
|
||||
|
||||
## Return value
|
||||
|
||||
`#!cpp true` if the view is discarded, `#!cpp false` otherwise.
|
||||
@@ -23,8 +27,9 @@ Constant.
|
||||
|
||||
## Notes
|
||||
|
||||
`#!cpp v.is_discarded()` and `#!cpp !static_cast<bool>(v)` are equivalent; use whichever reads better at the call
|
||||
site.
|
||||
A `basic_json_view` is not convertible to `#!cpp bool`: such a conversion would mean "refers to a value", whereas
|
||||
`basic_json` converts to the `#!cpp bool` it holds, so the same code would silently behave differently. Test
|
||||
`#!cpp !v.is_discarded()` explicitly.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -45,7 +50,7 @@ site.
|
||||
|
||||
## See also
|
||||
|
||||
- [operator bool](operator_bool.md) - return whether the view refers to a value
|
||||
- [operator[]](operator[].md) - access specified element; yields a discarded view where an element is missing
|
||||
- [(constructor)](basic_json_view.md) - the default constructor creates a discarded view
|
||||
- [is_discarded (basic_json_document)](../basic_json_document/is_discarded.md) - return whether the last parse failed
|
||||
- [`BasicJsonType::is_discarded`](../basic_json/is_discarded.md) - the corresponding function of `basic_json`
|
||||
|
||||
@@ -48,7 +48,7 @@ Constant.
|
||||
|
||||
As for [`begin()`](begin.md)/[`end()`](end.md), `items()` visits **every** member of an object, including all
|
||||
occurrences of a duplicate key -- unlike [`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md),
|
||||
[`contains`](contains.md), and [`count`](count.md), which resolve to the *first* member with a given key. See the
|
||||
[`contains`](contains.md), and [`count`](count.md), which resolve to the *last* member with a given key. See the
|
||||
[Notes on duplicate keys](operator[].md#notes) of `operator[]`.
|
||||
|
||||
!!! danger "Lifetime issues"
|
||||
@@ -63,8 +63,8 @@ occurrences of a duplicate key -- unlike [`operator[]`](operator[].md), [`at`](a
|
||||
|
||||
The example below shows a settings object whose source text records every update to a key as a duplicate
|
||||
member, in the order they happened. `items()` walks all of them, so the update history is visible, while
|
||||
[`operator[]`](operator[].md) only ever sees the *first* one and [`materialize()`](materialize.md) -- like
|
||||
[`BasicJsonType::parse()`](../basic_json/parse.md) -- keeps only the *last*.
|
||||
[`operator[]`](operator[].md) sees the *last* one, and so does [`materialize()`](materialize.md) -- like
|
||||
[`BasicJsonType::parse()`](../basic_json/parse.md).
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/basic_json_view__items.cpp"
|
||||
|
||||
@@ -8,16 +8,19 @@ basic_json_view operator[](const string_t& key) const;
|
||||
|
||||
// (2)
|
||||
basic_json_view operator[](size_type idx) const;
|
||||
basic_json_view operator[](int idx) const;
|
||||
template<typename IntegerType>
|
||||
basic_json_view operator[](IntegerType idx) const;
|
||||
|
||||
// (3)
|
||||
basic_json_view operator[](const json_pointer& ptr) const;
|
||||
```
|
||||
|
||||
1. Returns the value of the object member with key `key` -- the first one, should the key occur more than once (see
|
||||
1. Returns the value of the object member with key `key` -- the last one, should the key occur more than once (see
|
||||
the [Notes](#notes) below) -- or a [discarded](is_discarded.md) view if there is no such member.
|
||||
2. Returns the array element at index `idx`, or a [discarded](is_discarded.md) view if `idx` is out of range. (The
|
||||
`#!cpp int` overload only exists so that an integer literal is not ambiguous between this overload and 1.)
|
||||
2. Returns the array element at index `idx`, or a [discarded](is_discarded.md) view if `idx` is out of range. The
|
||||
template accepts every integer type except `#!cpp bool` and `#!cpp std::size_t` (`#!cpp int`, `#!cpp unsigned`,
|
||||
`#!cpp long`, `#!cpp std::int64_t`, ...) and forwards to the `size_type` overload, so that an integer argument is
|
||||
not ambiguous between that overload and 1; a negative `idx` is out of range.
|
||||
3. Returns the value a JSON pointer `ptr` refers to, starting at this value, or a [discarded](is_discarded.md) view
|
||||
wherever resolving it further is not possible without inserting into or extending the document (see
|
||||
[Return value](#return-value) and [Exceptions](#exceptions) below).
|
||||
@@ -35,10 +38,12 @@ basic_json_view operator[](const json_pointer& ptr) const;
|
||||
|
||||
## Return value
|
||||
|
||||
1. the value of the first member with key `key`, or a discarded view if `#!cpp is_object()` is `#!cpp false` or no
|
||||
member has this key
|
||||
2. the element at index `idx`, or a discarded view if `#!cpp is_array()` is `#!cpp false` or `#!cpp idx >= size()`
|
||||
3. the value `ptr` resolves to, starting at this value, or a discarded view for exactly the reference tokens where the
|
||||
1. the value of the last member with key `key`, or a discarded view if no member has this key (or if this view is
|
||||
[discarded](is_discarded.md))
|
||||
2. the element at index `idx`, or a discarded view if `#!cpp idx >= size()` or `idx` is negative (or if this view is
|
||||
[discarded](is_discarded.md))
|
||||
3. the value `ptr` resolves to, starting at this value, or a discarded view (also if this view is
|
||||
[discarded](is_discarded.md)) for exactly the reference tokens where the
|
||||
**const** overload of [`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) invokes undefined behavior for
|
||||
the same pointer and the same document: an object member that does not exist, or an array index that is out of
|
||||
range
|
||||
@@ -49,10 +54,12 @@ Strong exception safety: if an exception is thrown, there are no changes to the
|
||||
|
||||
## Exceptions
|
||||
|
||||
1. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an object --
|
||||
1. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an object and
|
||||
not [discarded](is_discarded.md) --
|
||||
the same exception, with the same message, that the **const** overload of
|
||||
[`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) throws for a string argument on a non-object value.
|
||||
2. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an array --
|
||||
2. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the value is not an array and
|
||||
not [discarded](is_discarded.md) --
|
||||
the same exception, with the same message, that the **const** overload of
|
||||
[`BasicJsonType::operator[]`](../basic_json/operator%5B%5D.md) throws for a numeric argument on a non-array value.
|
||||
3. Throws the same exceptions, with the same messages, that the **const** overload of
|
||||
@@ -73,9 +80,9 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics
|
||||
## Complexity
|
||||
|
||||
1. Linear in the number of members: as for [`ordered_json`](../ordered_json.md), members are compared one after
|
||||
another, in document order, stopping at the first match. Each comparison first checks the key's length --
|
||||
already known from the index, without reading the key bytes -- before comparing its content, so a key of a
|
||||
different length than `key` is rejected without touching the source text.
|
||||
another, in document order, scanning all of them, since the last match is wanted. Each comparison first checks the
|
||||
key's length -- already known from the index, without reading the key bytes -- before comparing its content, so a
|
||||
key of a different length than `key` is rejected without touching the source text.
|
||||
Objects with 128 or more members get a hash index while parsing, so that a lookup in them takes constant time
|
||||
on average.
|
||||
2. Linear in `idx`: elements are skipped one at a time from the first one, since they are not a fixed size in the
|
||||
@@ -86,20 +93,30 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics
|
||||
## Notes
|
||||
|
||||
Unlike `BasicJsonType::operator[]`, which is undefined behavior (guarded by a
|
||||
[runtime assertion](../../features/assertions.md)) for a missing key on a **const** value, this operator always
|
||||
returns a safe, testable result: a [discarded](is_discarded.md) view, which is `#!cpp false` in a boolean context.
|
||||
[runtime assertion](../../features/assertions.md)) for a missing key on a **const** value, this operator returns a
|
||||
safe, testable result for a missing key or an index out of range: a [discarded](is_discarded.md) view, which is
|
||||
tested with [`is_discarded`](is_discarded.md).
|
||||
There is also no non-const overload that inserts a missing key or extends an array -- a view never modifies the
|
||||
document.
|
||||
|
||||
!!! info "Chained access"
|
||||
|
||||
`#!cpp operator[]` on a [discarded](is_discarded.md) view returns a discarded view and does not throw, so a chain
|
||||
like `#!cpp v["a"]["b"][0]` is safe even if `"a"` or `"b"` is missing: the first missing step makes the whole
|
||||
result discarded, which is tested once at the end. Type errors on values that are *not* discarded still throw: a
|
||||
key on an array or a primitive, or an index on an object or a primitive, is `type_error.305` as for
|
||||
`BasicJsonType`. [`at`](at.md) still throws for a discarded view, as it does for a missing key.
|
||||
|
||||
!!! info "Duplicate keys"
|
||||
|
||||
If the source text has an object with a duplicate key, `#!cpp operator[]` (and [`at`](at.md), [`find`](find.md),
|
||||
[`contains`](contains.md), [`count`](count.md)) all resolve to the *first* member with that key, because a
|
||||
lookup can stop as soon as it finds a match. This is different from
|
||||
[`materialize()`](materialize.md) (and [`BasicJsonType::parse()`](../basic_json/parse.md)), which replay every
|
||||
member in order and so end up keeping the *last* value for a repeated key -- there is no reason for them to stop
|
||||
early. [`begin()`](begin.md)/[`end()`](end.md) and [`items()`](items.md) iterate over *all* members, including
|
||||
duplicates, in document order. See the example below and [`size()`](size.md#notes).
|
||||
[`contains`](contains.md), [`count`](count.md), [`value`](value.md), and JSON pointer resolution) all resolve to
|
||||
the *last* member with that key. This is the member [`materialize()`](materialize.md) (and
|
||||
[`BasicJsonType::parse()`](../basic_json/parse.md)) keeps, so a lookup in the view and in the materialized value
|
||||
agree. [`begin()`](begin.md)/[`end()`](end.md) and [`items()`](items.md) iterate over *all* members, including
|
||||
duplicates, in document order. A lookup in an object without a hash index scans all members for this: it cannot
|
||||
stop at the first match. The hash index of a larger object (128 members or more) leads to the last member of a key
|
||||
as well. See the example below and [`size()`](size.md#notes).
|
||||
|
||||
!!! info "JSON pointer resolution"
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
# <small>nlohmann::basic_json_view::</small>operator bool
|
||||
|
||||
```cpp
|
||||
explicit operator bool() const noexcept;
|
||||
```
|
||||
|
||||
Returns whether this view refers to a value, i.e. the negation of [`is_discarded()`](is_discarded.md). Being
|
||||
`#!cpp explicit`, this conversion is only considered in a boolean context (`#!cpp if (v)`, `#!cpp !v`, `#!cpp v &&
|
||||
...`), not for implicit conversions to other types.
|
||||
|
||||
## Return value
|
||||
|
||||
`#!cpp true` if the view refers to a value, `#!cpp false` if it is [discarded](is_discarded.md).
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: this function never throws exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below classifies several parsed documents by the type of their root value, without materializing any
|
||||
of them into a `BasicJsonType` value.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/basic_json_view__type_predicates.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/basic_json_view__type_predicates.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [is_discarded](is_discarded.md) - return whether the view is invalid
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -12,7 +12,7 @@ T value(const json_pointer& ptr, const T& default_value) const;
|
||||
string_t value(const json_pointer& ptr, const char* default_value) const;
|
||||
```
|
||||
|
||||
1. Returns the value of the object member with key `key` -- the first one, should the key occur more than once (see
|
||||
1. Returns the value of the object member with key `key` -- the last one, should the key occur more than once (see
|
||||
[Notes on duplicate keys](operator[].md#notes)) -- converted to `T`, or `default_value` if there is no such member.
|
||||
2. Returns the value a JSON pointer `ptr` refers to, starting at this value, converted to `T`, or `default_value` if
|
||||
`ptr` cannot be resolved.
|
||||
@@ -39,7 +39,7 @@ equivalent) deduce `string_t`, not `const char*`, for their return type and for
|
||||
|
||||
## Return value
|
||||
|
||||
1. the first member with key `key`, converted to `T`, or `default_value`
|
||||
1. the last member with key `key`, converted to `T`, or `default_value`
|
||||
2. the value `ptr` resolves to, converted to `T`, or `default_value`
|
||||
|
||||
## Exception safety
|
||||
@@ -68,8 +68,8 @@ None of these exceptions carry a [`JSON_DIAGNOSTICS`](../macros/json_diagnostics
|
||||
## Complexity
|
||||
|
||||
1. Linear in the number of members: as for [`operator[]`](operator[].md#complexity), members are compared one after
|
||||
another, in document order, stopping at the first match. Plus the complexity of converting the found member to
|
||||
`T` (see [`get`](get.md)).
|
||||
another, in document order, scanning all of them, since the last match is wanted. Plus the complexity of converting
|
||||
the found member to `T` (see [`get`](get.md)).
|
||||
Objects with 128 or more members get a hash index while parsing, so that a lookup in them takes constant time
|
||||
on average.
|
||||
2. Linear in the number of reference tokens of `ptr` and, for each token, in the number of members of the object at
|
||||
|
||||
@@ -8,10 +8,10 @@ int main()
|
||||
// the default constructor is the only public one: it creates an invalid
|
||||
// (discarded) view, useful as a "no value yet" placeholder
|
||||
nlohmann::json_view v;
|
||||
std::cout << static_cast<bool>(v) << ' ' << v.is_discarded() << '\n';
|
||||
std::cout << v.is_discarded() << '\n';
|
||||
|
||||
// views are trivially copyable handles (two pointers); the document owns
|
||||
// the actual data
|
||||
nlohmann::json_view copy = v;
|
||||
std::cout << static_cast<bool>(copy) << '\n';
|
||||
std::cout << copy.is_discarded() << '\n';
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
false true
|
||||
false
|
||||
true
|
||||
true
|
||||
@@ -7,8 +7,8 @@ int main()
|
||||
{
|
||||
// a settings object whose source text records every update to a key as
|
||||
// a duplicate member. items() visits all of them, in document order, so
|
||||
// the update history is visible; operator[] only ever sees the first
|
||||
// one, and materialize() -- like basic_json::parse() -- keeps the last
|
||||
// the update history is visible; operator[] and materialize() -- like
|
||||
// basic_json::parse() -- see the last one
|
||||
json_document updates = json_document::parse(R"({"retries": 1, "timeout": 30, "retries": 5})");
|
||||
const auto settings = updates.root();
|
||||
|
||||
@@ -17,6 +17,6 @@ int main()
|
||||
std::cout << item.key() << '=' << item.value().materialize().dump() << '\n';
|
||||
}
|
||||
|
||||
std::cout << "first \"retries\" seen by operator[]: " << settings["retries"].materialize().dump() << '\n';
|
||||
std::cout << "last \"retries\" seen by operator[]: " << settings["retries"].materialize().dump() << '\n';
|
||||
std::cout << "last \"retries\" kept by materialize(): " << settings.materialize()["retries"].dump() << '\n';
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
retries=1
|
||||
timeout=30
|
||||
retries=5
|
||||
first "retries" seen by operator[]: 1
|
||||
last "retries" seen by operator[]: 5
|
||||
last "retries" kept by materialize(): 5
|
||||
@@ -22,17 +22,19 @@ int main()
|
||||
std::cout << user["name"].materialize().dump();
|
||||
|
||||
// operator[] on a missing object key gives a discarded view -- test
|
||||
// it with a plain "if". The const overload of json::operator[]
|
||||
// it with is_discarded(). The const overload of json::operator[]
|
||||
// would instead be undefined behavior (guarded by an assertion) for
|
||||
// a missing key
|
||||
if (const auto email = user["email"])
|
||||
const auto email = user["email"];
|
||||
if (!email.is_discarded())
|
||||
{
|
||||
std::cout << " <" << email.materialize().dump() << ">";
|
||||
}
|
||||
|
||||
// the same holds for an array index past the end: a discarded view,
|
||||
// not undefined behavior
|
||||
if (const auto first_tag = user["tags"][0])
|
||||
const auto first_tag = user["tags"][0];
|
||||
if (!first_tag.is_discarded())
|
||||
{
|
||||
std::cout << " #" << first_tag.materialize().dump();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ int main()
|
||||
// a missing key or an out-of-range index along the path gives a
|
||||
// discarded view, exactly where const json::operator[] would be
|
||||
// undefined behavior for the same pointer
|
||||
if (const auto missing = root[json_pointer("/region/servers/5/metrics/cpu")])
|
||||
const auto missing = root[json_pointer("/region/servers/5/metrics/cpu")];
|
||||
if (!missing.is_discarded())
|
||||
{
|
||||
std::cout << missing.materialize().dump() << '\n';
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ int main()
|
||||
// parse without exceptions, are both discarded
|
||||
nlohmann::json_view invalid;
|
||||
json_document failed = json_document::parse("not json", /* allow_exceptions */ false);
|
||||
std::cout << static_cast<bool>(invalid) << ' ' << invalid.is_discarded() << '\n';
|
||||
std::cout << static_cast<bool>(failed.root()) << ' ' << failed.root().is_discarded() << '\n';
|
||||
std::cout << invalid.is_discarded() << '\n';
|
||||
std::cout << failed.root().is_discarded() << '\n';
|
||||
|
||||
// type() returns the same value_t enumeration as basic_json::type()
|
||||
std::cout << (d_object.root().type() == nlohmann::json::value_t::object) << '\n';
|
||||
|
||||
@@ -7,6 +7,6 @@ true
|
||||
true true
|
||||
true false
|
||||
false
|
||||
false true
|
||||
false true
|
||||
true
|
||||
true
|
||||
true
|
||||
@@ -81,6 +81,9 @@ Moving the document itself is fine and does **not** invalidate its views: the in
|
||||
that keeps its address across the move. Take a fresh view from [`root()`](../api/basic_json_document/root.md)
|
||||
whenever any of the other conditions above was not met.
|
||||
|
||||
Because a view dies with its document, [`root()`](../api/basic_json_document/root.md) is not callable on a temporary
|
||||
document: `#!cpp auto v = json_document::parse(text).root();` does not compile. Give the document a name first.
|
||||
|
||||
??? example "Example: borrowed and owned documents, and when views become invalid"
|
||||
|
||||
```cpp
|
||||
@@ -113,7 +116,7 @@ whenever any of the other conditions above was not met.
|
||||
|
||||
- **Only 64-bit integers.** `basic_json_document<BasicJsonType>` requires `BasicJsonType::number_integer_t` and
|
||||
`number_unsigned_t` to both be 64 bits wide; this is a compile-time `#!cpp static_assert`.
|
||||
- **A 4 GiB input limit.** An input of 4 GiB or more throws
|
||||
- **A 4 GiB input limit.** An input of 4294967280 bytes (4 GiB minus 16 bytes) or more throws
|
||||
[`out_of_range.416`](../home/exceptions.md#jsonexceptionout_of_range416), a limit
|
||||
`#!cpp basic_json::parse()` does not have.
|
||||
- **A stream is always read to its end.** There is no partial/streaming read of an `#!cpp std::istream`.
|
||||
@@ -126,14 +129,21 @@ whenever any of the other conditions above was not met.
|
||||
members in the order they appear in the source text. `basic_json`'s default `object_t` is a `std::map`, which
|
||||
sorts by key, so iterating a [`materialize()`](../api/basic_json_view/materialize.md)d value can print members in
|
||||
a different order than iterating the view they came from.
|
||||
- **Chained access is safe.** [`operator[]`](../api/basic_json_view/operator%5B%5D.md) with a missing key, an index
|
||||
out of range, or an unresolvable JSON pointer returns a [discarded](../api/basic_json_view/is_discarded.md) view, and
|
||||
`operator[]` on a discarded view returns a discarded view without throwing: `#!cpp v["a"]["b"][0]` can be tested
|
||||
once at the end. Type errors on values that exist (a key on an array, an index on an object) still throw, and
|
||||
[`at`](../api/basic_json_view/at.md) throws for every missing value.
|
||||
- **Duplicate keys are visible.** If an object in the source text repeats a key,
|
||||
[`begin()`](../api/basic_json_view/begin.md)/[`end()`](../api/basic_json_view/end.md) and
|
||||
[`items()`](../api/basic_json_view/items.md) visit *every* occurrence (and [`size()`](../api/basic_json_view/size.md)
|
||||
counts all of them), while [`operator[]`](../api/basic_json_view/operator%5B%5D.md),
|
||||
[`at`](../api/basic_json_view/at.md), [`find`](../api/basic_json_view/find.md),
|
||||
[`contains`](../api/basic_json_view/contains.md), and [`count`](../api/basic_json_view/count.md) resolve to the
|
||||
*first* occurrence, since a lookup can stop as soon as it finds a match. `basic_json::parse()` (and so
|
||||
[`materialize()`](../api/basic_json_view/materialize.md)) instead keeps only the *last* value for a repeated key.
|
||||
*last* occurrence -- the one `basic_json::parse()` (and so
|
||||
[`materialize()`](../api/basic_json_view/materialize.md)) keeps for a repeated key -- which makes a lookup scan all
|
||||
members instead of stopping at a match (objects with 128 members or more get a hash index that leads to the last
|
||||
occurrence directly).
|
||||
See the [Notes on duplicate keys](../api/basic_json_view/operator%5B%5D.md#notes) of `operator[]`.
|
||||
- **No [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) path.** Exceptions thrown by `basic_json_view`'s own
|
||||
element access and lookup functions never carry the JSON Pointer path `JSON_DIAGNOSTICS` would otherwise add: the
|
||||
|
||||
@@ -353,16 +353,21 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
||||
### Always required
|
||||
|
||||
- A member type `value_type` that is one byte wide and `char`-compatible. The library stores and processes UTF-8
|
||||
encoded `char` data and passes `data()` to functions that take a `#!cpp const char*`, such as `#!cpp std::strtod`.
|
||||
encoded `char` data and passes `data()` to functions that take a `#!cpp const char*`, such as `#!cpp std::strtold`
|
||||
(only used to parse a `#!cpp long double` that is not IEEE 754 binary64, see
|
||||
[`NumberFloatType`](#numberfloattype)).
|
||||
`#!cpp std::wstring`, `#!cpp std::u16string`, and `#!cpp std::u32string` are **not** valid choices; see the FAQ on
|
||||
[wide string handling](../../home/faq.md#wide-string-handling).
|
||||
- Constructors: default, copy, move, from `#!cpp const char*` (which must not be `#!cpp explicit`), from
|
||||
`#!cpp (const char*, size_type)`, and from `#!cpp (size_type, char)`; and copy or move assignment.
|
||||
- Member functions `size()`, `clear()`, `resize(n, c)`, `data()`, `push_back(char)`, and `operator[]`
|
||||
(const and non-const, returning references). `c_str()` and `back()` are **not** required.
|
||||
- `data()` must return a pointer to a contiguous, **null-terminated** buffer -- the parser may hand it to
|
||||
`#!cpp std::strtod`, which reads up to the null character. A type whose `data()` is not null-terminated does not
|
||||
fail to compile; it can silently misparse floating-point numbers.
|
||||
- `data()` must return a pointer to a contiguous, **null-terminated** buffer. `#!cpp float`, `#!cpp double`, and a
|
||||
`#!cpp long double` that is IEEE 754 binary64 are converted by the library itself and do not depend on this. For any
|
||||
other `NumberFloatType` (a `#!cpp long double` of another format), the parser falls back to `#!cpp std::strtold` when
|
||||
`#!cpp std::from_chars` is not available or declines the token, and `std::strtold` reads up to the null character. A type whose `data()`
|
||||
is not null-terminated does not fail to compile; with such a `NumberFloatType` it can silently misparse
|
||||
floating-point numbers.
|
||||
- `append(const char*, size_type)`, used by [`dump`](../../api/basic_json/dump.md), and `append(const StringType&)`,
|
||||
used by the CBOR reader for indefinite-length strings. The library's internal string concatenation additionally has
|
||||
to append a `#!cpp char` and a `#!cpp const char*`; for each it selects between `append(arg)`, `#!cpp operator+=`,
|
||||
|
||||
@@ -210,12 +210,13 @@ packet-beta
|
||||
- **Navigation** needs no pointers: the elements of an array or object follow its node, and the node after a value's
|
||||
subtree is `next` nodes further for an array or object, and the next node otherwise (`document_data::after`). Views
|
||||
step from element to element this way and skip whole subtrees in constant time.
|
||||
- **Offsets** are 32 bits wide, so a document is limited to 4 GiB (`out_of_range.416`).
|
||||
- **Offsets** are 32 bits wide, so a document is limited to 4294967279 bytes, 4 GiB minus 16 bytes (a margin below
|
||||
2^32 for positions one scanner step past the end of the text; `out_of_range.416`).
|
||||
- **Large objects** (128 members or more) get a hash index after parsing
|
||||
([`detail/view/object_index.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/view/object_index.hpp)):
|
||||
an open-addressing table whose slots hold the distance from the object's node to a key's node, so that a lookup does
|
||||
not compare every key. The object's `extra` holds the number of its table. Only 65,535 tables fit into `extra`;
|
||||
objects beyond them are searched linearly.
|
||||
not compare every key. Of duplicate keys the table leads to the last, as a linear search does. The object's `extra`
|
||||
holds the number of its table. Only 65,535 tables fit into `extra`; objects beyond them are searched linearly.
|
||||
|
||||
For example, `#!json {"a": [1, 2.5]}` becomes five nodes. Each node's elements follow it, and `next` leads from an
|
||||
array or object past its subtree:
|
||||
|
||||
@@ -824,8 +824,9 @@ does not list an enumerator and it is therefore converted like the first listed
|
||||
|
||||
### json.exception.type_error.319
|
||||
|
||||
[`basic_json_document::set`](../api/basic_json_document/set.md) and
|
||||
[`basic_json_document::push_back`](../api/basic_json_document/push_back.md) can store any `basic_json` value except
|
||||
[`basic_json_document::set`](../api/basic_json_document/set.md),
|
||||
[`basic_json_document::push_back`](../api/basic_json_document/push_back.md), and
|
||||
[`basic_json_document::insert`](../api/basic_json_document/insert.md) can store any `basic_json` value except
|
||||
a binary one: a `json_document` has no representation for [binary values](../features/binary_values.md), which only
|
||||
ever arise from parsing a binary format or from an explicit [`json::binary`](../api/basic_json/binary.md) value, not
|
||||
from JSON text.
|
||||
@@ -1103,7 +1104,7 @@ MessagePack's ext type and BSON's binary subtype are each stored in a single byt
|
||||
|
||||
[`basic_json_document::parse()`](../api/basic_json_document/parse.md) and the other parsing functions of
|
||||
[`basic_json_document`](../api/basic_json_document/index.md) index a value's position in the source text in 32 bits,
|
||||
so they do not support an input of 4 GiB or more. The same 32-bit limit applies to an **editable** document's own
|
||||
so they do not support an input of 4294967280 bytes (4 GiB minus 16 bytes) or more. The same 32-bit limit applies to an **editable** document's own
|
||||
storage: [`set`](../api/basic_json_document/set.md) and [`push_back`](../api/basic_json_document/push_back.md) throw
|
||||
this exception once the strings and number tokens written by edits reach 4 GiB in total, or once more than
|
||||
4294967295 arrays/objects have had an element set or appended to them. The same limit applies to an
|
||||
@@ -1113,7 +1114,7 @@ count, the text, or the decoded strings it would write would individually reach
|
||||
!!! failure "Example messages"
|
||||
|
||||
```
|
||||
[json.exception.out_of_range.416] input of 4 GiB or more is not supported by json_document
|
||||
[json.exception.out_of_range.416] input of 4294967280 bytes or more is not supported by json_document
|
||||
```
|
||||
```
|
||||
[json.exception.out_of_range.416] edits of 4 GiB or more are not supported by json_document
|
||||
|
||||
@@ -18,7 +18,7 @@ The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed und
|
||||
|
||||
The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
||||
|
||||
The class contains a port of the shortest double-to-decimal conversion of [Żmij](https://github.com/vitaut/zmij) by Victor Zverovich, which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2025 [Victor Zverovich](https://github.com/vitaut)
|
||||
The class contains a port of the shortest double-to-decimal conversion of [Żmij](https://github.com/vitaut/zmij) by Victor Zverovich, including the conversion of the digits to text by Xiang JunBo and the SIMD instruction sequence of Dougall Johnson, which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2025 [Victor Zverovich](https://github.com/vitaut)
|
||||
|
||||
The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
||||
|
||||
@@ -289,7 +289,6 @@ nav:
|
||||
- 'materialize': api/basic_json_view/materialize.md
|
||||
- 'number_format': api/basic_json_view/number_format.md
|
||||
- 'number_token': api/basic_json_view/number_token.md
|
||||
- 'operator bool': api/basic_json_view/operator_bool.md
|
||||
- 'operator<<': api/basic_json_view/operator_ltlt.md
|
||||
- 'operator[]': api/basic_json_view/operator[].md
|
||||
- 'operator==': api/basic_json_view/operator_eq.md
|
||||
|
||||
Reference in new issue
Block a user