mirror of
https://github.com/nlohmann/json.git
synced 2026-10-13 04:15:17 +00:00
Add editable json_documents: set, push_back, insert, and erase
basic_json_document gets a second template parameter, Editable (false by default), plus the aliases json_editable_document, json_editable_view, ordered_json_editable_document and ordered_json_editable_view. Editable documents can change values and structure without rewriting the source text: set()/push_back() on values, keys, array indices and JSON pointers; insert() before an array element; erase() of an object key, array index or JSON pointer. New values and element sequences go into edit storage that the document owns and never moves, so views keep referring to their value across edits and a parsed node never moves. Read-only documents walk the plain node array and are unaffected. Strings are checked for UTF-8 on entry, so dump() of an editable document never throws type_error.316. Binary values cannot be stored (type_error.319). A seeded differential test applies random edits to an editable document and to the equivalent ordered_json and compares both after every step. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
128
docs/mkdocs/docs/api/basic_json_document/erase.md
Normal file
128
docs/mkdocs/docs/api/basic_json_document/erase.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# <small>nlohmann::basic_json_document::</small>erase
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
std::size_t erase(view_type object, string_view_t key);
|
||||
|
||||
// (2)
|
||||
template<typename I>
|
||||
void erase(view_type array, I idx);
|
||||
|
||||
// (3)
|
||||
std::size_t erase(const json_pointer& ptr);
|
||||
```
|
||||
|
||||
Only an **editable** document (`#!cpp Editable == true`, e.g. [`json_editable_document`](../json_editable_document.md))
|
||||
has `erase`; calling it on a read-only `basic_json_document` fails to compile (`#!cpp static_assert`).
|
||||
|
||||
1. Removes every member of `object` whose key is `key` (see [Notes](#notes) on duplicate keys) and returns how many
|
||||
were removed; `#!cpp 0` if `object` has no member with this key.
|
||||
2. Removes the element at index `idx` of `array`, which must already exist (`#!cpp idx < array.size()`).
|
||||
3. Removes the value the JSON pointer `ptr` refers to, relative to [`root()`](root.md), and returns how many values
|
||||
were removed: the *parent* of the target must already exist, and the target itself is removed as in 1. (an object
|
||||
member; `#!cpp 0` or more) or 2. (an array element; always `#!cpp 1`). `ptr` must not be empty -- [`root()`](root.md)
|
||||
itself cannot be erased.
|
||||
|
||||
## Template parameters
|
||||
|
||||
`I`
|
||||
: an integral type other than `#!cpp bool`, deduced (overloads taking a `#!cpp bool` or a non-integral type for
|
||||
`idx` do not participate in overload resolution).
|
||||
|
||||
## Parameters
|
||||
|
||||
`object` (in)
|
||||
: the object to remove a member of
|
||||
|
||||
`array` (in)
|
||||
: the array to remove an element of
|
||||
|
||||
`key` (in)
|
||||
: the key of the member(s) to remove
|
||||
|
||||
`idx` (in)
|
||||
: the index of the element to remove; a negative value throws (see [Exceptions](#exceptions))
|
||||
|
||||
`ptr` (in)
|
||||
: a JSON pointer to the value to remove, relative to `root()`
|
||||
|
||||
## Return value
|
||||
|
||||
1. the number of removed members (`#!cpp 0` if `object` had none with this `key`)
|
||||
2. (nothing)
|
||||
3. the number of removed values (`#!cpp 0` or more for an object member, always `#!cpp 1` for an array element)
|
||||
|
||||
## Exceptions
|
||||
|
||||
1. Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) if `object` is not an object -- the
|
||||
same message [`BasicJsonType::erase`](../basic_json/erase.md) throws for the same type.
|
||||
2. Throws `type_error.307` if `array` is not an array. Throws
|
||||
[`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if `idx` is negative, or if
|
||||
`#!cpp idx >= array.size()`.
|
||||
3. Throws [`out_of_range.405`](../../home/exceptions.md#jsonexceptionout_of_range405) ("JSON pointer has no parent")
|
||||
if `ptr` is empty. Throws what [`at`](../basic_json_view/at.md) throws (overload 3) for resolving `ptr`'s parent.
|
||||
For the last reference token itself: if the parent is an array, throws what 2. throws for an index that is out of
|
||||
range, or, for a token that is not a valid array index,
|
||||
[`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); otherwise (an
|
||||
object, or a primitive value the pointer's parent resolves to) throws what 1. throws.
|
||||
|
||||
Every overload also throws [`invalid_iterator.202`](../../home/exceptions.md#jsonexceptioninvalid_iterator202) ("view
|
||||
does not belong to this document") if `object`/`array` is a [discarded](../basic_json_view/is_discarded.md) view or a
|
||||
view of a *different* document (overloads 1-2 only; overload 3 always starts from this document's own
|
||||
[`root()`](root.md)).
|
||||
|
||||
## Complexity
|
||||
|
||||
1. Linear in the number of members of `object`.
|
||||
2. Linear in the number of elements of `array` at or after `idx` (they move one slot over).
|
||||
3. 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 1. or 2. for
|
||||
the last token.
|
||||
|
||||
## Notes
|
||||
|
||||
!!! 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
|
||||
more than one member removed, or none.
|
||||
|
||||
Like [`set`](set.md) and [`push_back`](push_back.md), `erase` never moves an element's *value*: a view still
|
||||
referring to a removed member or element keeps showing what it last held (see [Edits](index.md#edits)) -- it just no
|
||||
longer appears when `array`/`object` is read, dumped, or iterated. Removing an element of `array` (2.) does shift the
|
||||
*links* to the elements after it, the same way `insert`, `set`, or `push_back` on the same array would; any iterator
|
||||
already taken over `array`/`object` is invalidated by an erase, since it was walking the old layout.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below drops a deprecated field and a decommissioned entry from a configuration document -- using all
|
||||
three overloads -- and shows what stays intact that would not with a plain `json`/`ordered_json` value: the order
|
||||
of the fields around the ones removed, and the exact spelling of a number that was never touched.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/basic_json_document__erase.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/basic_json_document__erase.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [insert](insert.md) - insert an element into an array
|
||||
- [set](set.md) - replace a value, or set an object member, an array element, or the value a JSON pointer refers to
|
||||
- [push_back](push_back.md) - append to an array
|
||||
- [root](root.md) - the view of the root value, the starting point of overload 3
|
||||
- [`BasicJsonType::erase`](../basic_json/erase.md) - the corresponding function of `basic_json`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -3,7 +3,7 @@
|
||||
<small>Defined in header `<nlohmann/json_view.hpp>`</small>
|
||||
|
||||
```cpp
|
||||
template<typename BasicJsonType>
|
||||
template<typename BasicJsonType, bool Editable = false>
|
||||
class basic_json_document;
|
||||
```
|
||||
|
||||
@@ -19,6 +19,11 @@ it (a copy, or an rvalue `#!cpp std::string` that was moved in); see [`owns_sour
|
||||
is move-only: copying a document would either duplicate a potentially large index and text, or leave two documents
|
||||
claiming to borrow the same buffer, so it is disabled.
|
||||
|
||||
With `#!cpp Editable == true`, the document also offers [`set`](set.md), [`push_back`](push_back.md),
|
||||
[`insert`](insert.md), and [`erase`](erase.md) to change values in place, see [Edits](#edits) below. The source text
|
||||
itself is never written; a read-only document (`#!cpp Editable == false`, the default) does not carry any of the
|
||||
bookkeeping edits need, and calling any of them on one fails to compile (`#!cpp static_assert`).
|
||||
|
||||
## Template parameters
|
||||
|
||||
`BasicJsonType`
|
||||
@@ -26,14 +31,22 @@ claiming to borrow the same buffer, so it is disabled.
|
||||
[`ordered_json`](../ordered_json.md). Only 64-bit `number_integer_t`/`number_unsigned_t` types are supported; this
|
||||
is checked with a `static_assert`.
|
||||
|
||||
`Editable`
|
||||
: whether the document supports [`set`](set.md), [`push_back`](push_back.md), [`insert`](insert.md), and
|
||||
[`erase`](erase.md) (optional, `#!cpp false` by default). See [Edits](#edits) below.
|
||||
|
||||
## Specializations
|
||||
|
||||
- [**json_document**](../json_document.md) - documents of the default specialization [`json`](../json.md)
|
||||
- [**ordered_json_document**](../ordered_json_document.md) - documents of [`ordered_json`](../ordered_json.md)
|
||||
- [**json_document**](../json_document.md) - read-only documents of the default specialization [`json`](../json.md)
|
||||
- [**ordered_json_document**](../ordered_json_document.md) - read-only documents of
|
||||
[`ordered_json`](../ordered_json.md)
|
||||
- [**json_editable_document**](../json_editable_document.md) - editable documents of [`json`](../json.md)
|
||||
- [**ordered_json_editable_document**](../ordered_json_editable_document.md) - editable documents of
|
||||
[`ordered_json`](../ordered_json.md)
|
||||
|
||||
## Member types
|
||||
|
||||
- **view_type** - the type of view returned by [`root()`](root.md) (`#!cpp basic_json_view<BasicJsonType>`)
|
||||
- **view_type** - the type of view returned by [`root()`](root.md) (`#!cpp basic_json_view<BasicJsonType, Editable>`)
|
||||
- **value_t** - the JSON type enumeration, see [`basic_json::value_t`](../basic_json/value_t.md)
|
||||
|
||||
## Member functions
|
||||
@@ -50,6 +63,41 @@ claiming to borrow the same buffer, so it is disabled.
|
||||
- [**node_count**](node_count.md) - the number of index entries (values plus object keys)
|
||||
- [**memory_usage**](memory_usage.md) - the number of bytes held by the document
|
||||
- [**shrink_to_fit**](shrink_to_fit.md) - release unused index capacity
|
||||
- [**set**](set.md) - replace a value, or set an object member, an array element, or the value a JSON pointer refers
|
||||
to (`#!cpp Editable` documents only)
|
||||
- [**push_back**](push_back.md) - append to an array (`#!cpp Editable` documents only)
|
||||
- [**insert**](insert.md) - insert an element into an array before a given position (`#!cpp Editable` documents only)
|
||||
- [**erase**](erase.md) - remove an object member, an array element, or the value a JSON pointer refers to
|
||||
(`#!cpp Editable` documents only)
|
||||
|
||||
## Edits
|
||||
|
||||
An editable document (`#!cpp Editable == true`) can be changed after parsing, with [`set`](set.md),
|
||||
[`push_back`](push_back.md), [`insert`](insert.md), and [`erase`](erase.md);
|
||||
[`json_editable_document`](../json_editable_document.md) and
|
||||
[`ordered_json_editable_document`](../ordered_json_editable_document.md) are the corresponding specializations. A few
|
||||
points apply to every edit:
|
||||
|
||||
- **The source text is never written**, and the parsed index never moves: every value keeps the node it was parsed
|
||||
into, so [views](../basic_json_view/index.md) taken before an edit stay valid, including
|
||||
[`root()`](root.md). New values (and the element sequences of an edited array/object) go to storage owned by the
|
||||
document, allocated on demand.
|
||||
- **A view keeps referring to the same value.** After [`set`](set.md) replaces the value a view refers to, that view
|
||||
sees the new value; a view of a value that a later edit replaces or drops keeps showing what it last held. An edit
|
||||
of an array or object, however, **invalidates the iterators taken over it** (its members may now live in a
|
||||
different sequence), and a string obtained with [`get_string()`](../basic_json_view/get_string.md) stays valid even
|
||||
as further edits happen (earlier buffers of edited text are kept alive, not overwritten).
|
||||
- **Values are accepted three ways:** a [`basic_json_view`](../basic_json_view/index.md) of *any* document
|
||||
(read-only or editable; it is copied, nothing is shared with the source document), a `BasicJsonType` value, or
|
||||
anything `BasicJsonType` can be constructed from (numbers, strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...).
|
||||
- [`dump()`](../basic_json_view/dump.md) writes an edited document with members in document order, new members at
|
||||
the end, and, with [`number_format::source`](../basic_json_view/number_format.md), keeps the spelling of every
|
||||
number that was not itself edited -- see [Editing a document](../../features/json_view.md#editing-a-document) for
|
||||
why this matters.
|
||||
- [`read()`](read.md) discards all edits, [`shrink_to_fit()`](shrink_to_fit.md) does not move the node index once
|
||||
there are edits, and [`memory_usage()`](memory_usage.md) includes the memory edits use.
|
||||
[`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.
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
114
docs/mkdocs/docs/api/basic_json_document/insert.md
Normal file
114
docs/mkdocs/docs/api/basic_json_document/insert.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# <small>nlohmann::basic_json_document::</small>insert
|
||||
|
||||
```cpp
|
||||
template<typename I, typename V>
|
||||
view_type insert(view_type array, I idx, V&& value);
|
||||
```
|
||||
|
||||
Only an **editable** document (`#!cpp Editable == true`, e.g. [`json_editable_document`](../json_editable_document.md))
|
||||
has `insert`; calling it on a read-only `basic_json_document` fails to compile (`#!cpp static_assert`).
|
||||
|
||||
Inserts `value` into `array` as a new element before position `idx`, which must not be past the end
|
||||
(`#!cpp idx <= array.size()`; `#!cpp idx == array.size()` appends, like [`push_back`](push_back.md)). Unlike
|
||||
[`push_back`](push_back.md), a [null](../basic_json_view/is_null.md) `array` does *not* first become an empty array:
|
||||
`array` must already be an array.
|
||||
|
||||
`value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any* document -- read-only or
|
||||
editable, and it does not have to be `array`'s own document -- which is copied so that nothing is shared with the
|
||||
source document afterward; a `BasicJsonType` value; or anything `BasicJsonType` can be constructed from (numbers,
|
||||
strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...).
|
||||
|
||||
## Template parameters
|
||||
|
||||
`I`
|
||||
: an integral type other than `#!cpp bool`, deduced (overloads taking a `#!cpp bool` or a non-integral type for
|
||||
`idx` do not participate in overload resolution).
|
||||
|
||||
`V`
|
||||
: the type of `value`, deduced; see above for what is accepted.
|
||||
|
||||
## Parameters
|
||||
|
||||
`array` (in)
|
||||
: the array to insert into
|
||||
|
||||
`idx` (in)
|
||||
: the position to insert `value` before; a negative value throws (see [Exceptions](#exceptions))
|
||||
|
||||
`value` (in)
|
||||
: the value to insert
|
||||
|
||||
## Return value
|
||||
|
||||
a view of the new element, now holding `value`
|
||||
|
||||
## Exception safety
|
||||
|
||||
Basic exception safety: `value` is fully encoded -- including the checks below -- into storage owned by the document
|
||||
before anything already reachable from [`root()`](root.md) is touched, so a failure while encoding `value` (an
|
||||
invalid argument, or `#!cpp std::bad_alloc`) leaves the document completely unchanged, other than memory allocated
|
||||
for the encoding that is not reclaimed. A failure of a later allocation -- while `array` switches from its parsed
|
||||
layout to a growable block, or while that block grows, see [Notes](#notes) -- can still leave `array` already
|
||||
switched to that layout even though `value` itself was not inserted.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Throws [`type_error.309`](../../home/exceptions.md#jsonexceptiontype_error309) if `array` is not an array -- the same
|
||||
message [`BasicJsonType::insert`](../basic_json/insert.md) throws for the same type; a null `array` throws this too
|
||||
(see above). Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if `idx` is negative,
|
||||
or if `#!cpp idx > array.size()`. Throws
|
||||
[`invalid_iterator.202`](../../home/exceptions.md#jsonexceptioninvalid_iterator202) ("view does not belong to this
|
||||
document") if `array` is a [discarded](../basic_json_view/is_discarded.md) view or a view of a *different* document.
|
||||
Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `value` is a
|
||||
[discarded](../basic_json_view/is_discarded.md) view or a [discarded](../basic_json/is_discarded.md) `BasicJsonType`
|
||||
value, and [`type_error.319`](../../home/exceptions.md#jsonexceptiontype_error319) if `value` is (or contains) a
|
||||
binary value -- `BasicJsonType` can hold one, but a `json_document` cannot. Throws
|
||||
[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316) if `value` is (or contains) a string that is
|
||||
not valid UTF-8, with the same message [`BasicJsonType::dump()`](../basic_json/dump.md) gives for that string.
|
||||
|
||||
## Complexity
|
||||
|
||||
Linear in the number of elements of `array` at or after `idx` (they move one slot over), plus time linear in the
|
||||
size of `value` to encode it into the document's storage (constant for a scalar, linear in the number of nested
|
||||
values for an array or object): like [`push_back`](push_back.md), the elements of `array` move to a growable block
|
||||
of links the first time it is inserted into (or [`set`](set.md)/[`push_back`](push_back.md) on), and that block
|
||||
grows in amortized constant time; inserting before the end within that block still shifts every later element.
|
||||
|
||||
## Notes
|
||||
|
||||
Like [`set`](set.md) on a member or an element, `insert` never moves an existing *element's value* -- only where
|
||||
`array`'s *links* to its elements live -- so a view of an existing element of `array` stays valid across an
|
||||
`insert`, and keeps referring to the same element even though its index shifts. Any iterator already taken over
|
||||
`array` is invalidated, since it was walking the old layout. See [Edits](index.md#edits) for what stays valid across
|
||||
an edit in general.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below inserts a step into the middle of a deployment plan, without touching the steps that come
|
||||
after it, and shows that a view taken before the insert keeps referring to the same element even though its
|
||||
index shifts -- something a plain `json`/`ordered_json` array, or its `std::vector`-based storage, has no
|
||||
equivalent for.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/basic_json_document__insert.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/basic_json_document__insert.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [push_back](push_back.md) - append to an array
|
||||
- [erase](erase.md) - remove an object member, an array element, or the value a JSON pointer refers to
|
||||
- [set](set.md) - replace a value, or set an object member, an array element, or the value a JSON pointer refers to
|
||||
- [`BasicJsonType::insert`](../basic_json/insert.md) - the corresponding function of `basic_json`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
102
docs/mkdocs/docs/api/basic_json_document/push_back.md
Normal file
102
docs/mkdocs/docs/api/basic_json_document/push_back.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# <small>nlohmann::basic_json_document::</small>push_back
|
||||
|
||||
```cpp
|
||||
template<typename V>
|
||||
view_type push_back(view_type array, V&& value);
|
||||
```
|
||||
|
||||
Appends `value` as a new last element of `array`. A [null](../basic_json_view/is_null.md) `array` first becomes an
|
||||
empty array, the same way [`set`](set.md) turns a null `object` into an empty object.
|
||||
|
||||
`value` is accepted three ways: a [`basic_json_view`](../basic_json_view/index.md) of *any* document -- read-only or
|
||||
editable, and it does not have to be `array`'s own document -- which is copied so that nothing is shared with the
|
||||
source document afterward; a `BasicJsonType` value; or anything `BasicJsonType` can be constructed from (numbers,
|
||||
strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...).
|
||||
|
||||
Only an **editable** document (`#!cpp Editable == true`, e.g. [`json_editable_document`](../json_editable_document.md))
|
||||
has `push_back`; calling it on a read-only `basic_json_document` fails to compile (`#!cpp static_assert`).
|
||||
|
||||
## Template parameters
|
||||
|
||||
`V`
|
||||
: the type of `value`, deduced; see above for what is accepted.
|
||||
|
||||
## Parameters
|
||||
|
||||
`array` (in)
|
||||
: the array (or null value) to append to
|
||||
|
||||
`value` (in)
|
||||
: the value to append
|
||||
|
||||
## Return value
|
||||
|
||||
a view of the new last element of `array`, now holding `value`
|
||||
|
||||
## Exception safety
|
||||
|
||||
Basic exception safety: `value` is fully encoded -- including the checks below -- into storage owned by the document
|
||||
before anything already reachable from [`root()`](root.md) is touched, so a failure while encoding `value` (an
|
||||
invalid argument, or `#!cpp std::bad_alloc`) leaves the document completely unchanged, other than memory allocated
|
||||
for the encoding that is not reclaimed. A failure of a later allocation -- while `array` switches from its parsed
|
||||
layout to a growable block, or while that block grows, see [Notes](#notes) -- can still leave a partial effect, such
|
||||
as a null `array` argument already turned into an empty array even though `value` itself was not appended.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) if `array` is neither an array nor
|
||||
null -- the same message [`BasicJsonType::push_back`](../basic_json/push_back.md) throws for the same type. Throws
|
||||
[`invalid_iterator.202`](../../home/exceptions.md#jsonexceptioninvalid_iterator202) ("view does not belong to this
|
||||
document") if `array` is a [discarded](../basic_json_view/is_discarded.md) view or a view of a *different* document.
|
||||
Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `value` is a
|
||||
[discarded](../basic_json_view/is_discarded.md) view or a [discarded](../basic_json/is_discarded.md) `BasicJsonType`
|
||||
value, and [`type_error.319`](../../home/exceptions.md#jsonexceptiontype_error319) if `value` is (or contains) a
|
||||
binary value -- `BasicJsonType` can hold one, but a `json_document` cannot. Throws
|
||||
[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316) if `value` is (or contains) a string that is
|
||||
not valid UTF-8, with the same message [`BasicJsonType::dump()`](../basic_json/dump.md) gives for that string.
|
||||
|
||||
## Complexity
|
||||
|
||||
Amortized constant, plus time linear in the size of `value` to encode it into the document's storage (constant for
|
||||
a scalar, linear in the number of nested values for an array or object): the elements of `array` move to a growable
|
||||
block of links the first time it is appended to (or [`set`](set.md) on), and that block itself grows -- doubling its
|
||||
capacity, so the cost of growing it amortizes to constant per element -- only once it runs out of room. See
|
||||
[Notes](#notes).
|
||||
|
||||
## Notes
|
||||
|
||||
Like [`set`](set.md) on a member or an element, `push_back` never moves an existing element itself -- only where
|
||||
`array`'s *links* to its elements live -- so a view of an existing element of `array` stays valid across a
|
||||
`push_back`, but any iterator already taken over `array` is invalidated, since it was walking the old layout. See
|
||||
[Edits](index.md#edits) for what stays valid across an edit in general.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below appends records to an array one at a time, as they might arrive from a stream of events,
|
||||
without ever building a `BasicJsonType` value for the array or for the records already in it, and shows that a
|
||||
view taken from an earlier `push_back` still refers to the same element once later ones have run.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/basic_json_document__push_back.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/basic_json_document__push_back.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [set](set.md) - replace a value, or set an object member, an array element, or the value a JSON pointer refers to
|
||||
- [insert](insert.md) - insert an element into an array before a given position
|
||||
- [erase](erase.md) - remove an object member, an array element, or the value a JSON pointer refers to
|
||||
- [root](root.md) - the view of the root value
|
||||
- [`BasicJsonType::push_back`](../basic_json/push_back.md) - the corresponding function of `basic_json`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
194
docs/mkdocs/docs/api/basic_json_document/set.md
Normal file
194
docs/mkdocs/docs/api/basic_json_document/set.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# <small>nlohmann::basic_json_document::</small>set
|
||||
|
||||
```cpp
|
||||
// (1)
|
||||
template<typename V>
|
||||
view_type set(view_type target, V&& value);
|
||||
|
||||
// (2)
|
||||
template<typename V>
|
||||
view_type set(view_type object, string_view_t key, V&& value);
|
||||
|
||||
// (3)
|
||||
template<typename I, typename V>
|
||||
view_type set(view_type array, I idx, V&& value);
|
||||
|
||||
// (4)
|
||||
template<typename V>
|
||||
view_type set(const json_pointer& ptr, V&& value);
|
||||
```
|
||||
|
||||
Only an **editable** document (`#!cpp Editable == true`, e.g. [`json_editable_document`](../json_editable_document.md))
|
||||
has `set`; calling it on a read-only `basic_json_document` fails to compile (`#!cpp static_assert`).
|
||||
|
||||
1. Replaces the value `target` refers to with `value`.
|
||||
2. Sets the member `key` of the object `object` to `value`: assigns it if `object` already has a member with this
|
||||
key -- the first one, should the key occur more than once, and the later duplicates are then dropped (see the
|
||||
[Notes](#notes) below) -- or appends a new member at the end otherwise. A [null](../basic_json_view/is_null.md)
|
||||
`object` first becomes an empty object.
|
||||
3. Assigns `value` to the element at index `idx` of the array `array`, which must already exist (`#!cpp idx <
|
||||
array.size()`).
|
||||
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.
|
||||
|
||||
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
|
||||
is copied so that nothing is shared with the source document afterward; a `BasicJsonType` value; or anything
|
||||
`BasicJsonType` can be constructed from (numbers, strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...).
|
||||
|
||||
## Template parameters
|
||||
|
||||
`V`
|
||||
: the type of `value`, deduced; see above for what is accepted.
|
||||
|
||||
`I`
|
||||
: an integral type other than `#!cpp bool`, deduced (overloads taking a `#!cpp bool` or a non-integral type for
|
||||
`idx` do not participate in overload resolution).
|
||||
|
||||
## Parameters
|
||||
|
||||
`target` (in)
|
||||
: the value to replace
|
||||
|
||||
`object` (in)
|
||||
: the object (or null value) whose member to set
|
||||
|
||||
`array` (in)
|
||||
: the array whose element to assign
|
||||
|
||||
`key` (in)
|
||||
: the key of the member to set
|
||||
|
||||
`idx` (in)
|
||||
: the index of the element to assign; a negative value throws (see [Exceptions](#exceptions))
|
||||
|
||||
`ptr` (in)
|
||||
: a JSON pointer to the value to set, relative to `root()`
|
||||
|
||||
`value` (in)
|
||||
: the new value
|
||||
|
||||
## Return value
|
||||
|
||||
1. a view of `target`, now holding `value`
|
||||
2. a view of the member `key` of `object`, now holding `value`
|
||||
3. a view of the element `idx` of `array`, now holding `value`
|
||||
4. a view of the value `ptr` refers to, now holding `value`
|
||||
|
||||
## Exception safety
|
||||
|
||||
Basic exception safety: `value` is fully encoded -- including the checks below -- into storage owned by the document
|
||||
before anything already reachable from [`root()`](root.md) is touched, so a failure while encoding `value` (an
|
||||
invalid argument, or `#!cpp std::bad_alloc`) leaves the document completely unchanged, other than memory allocated
|
||||
for the encoding that is not reclaimed. A failure of a later allocation -- while an edited array or object switches
|
||||
from its parsed layout to a growable block, see [Notes](#notes) -- can still leave a partial effect, such as a
|
||||
[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.
|
||||
|
||||
## Exceptions
|
||||
|
||||
1. Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `value` is a
|
||||
[discarded](../basic_json_view/is_discarded.md) view, or a [discarded](../basic_json/is_discarded.md)
|
||||
`BasicJsonType` value (e.g. `#!cpp BasicJsonType(value_t::discarded)`) -- an object or array `value`, of either
|
||||
kind, is fine and is encoded as a whole subtree.
|
||||
2. Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if `object` is neither an object
|
||||
nor null -- the same message [`operator[]`](../basic_json_view/operator%5B%5D.md) throws for a string argument on
|
||||
such a value. Throws [`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316) if `key` is not
|
||||
valid UTF-8, with the same message [`BasicJsonType::dump()`](../basic_json/dump.md) gives for that string.
|
||||
Also throws what 1. throws for `value`.
|
||||
3. Throws `type_error.305` if `array` is not an array -- the same message `operator[]` throws for a numeric argument
|
||||
on such a value. Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if `idx` is
|
||||
negative, or if `#!cpp idx >= array.size()`. Also throws what 1. throws for `value`.
|
||||
4. Throws what [`at`](../basic_json_view/at.md) throws (overload 3) for resolving `ptr`'s parent, except that a
|
||||
missing object member or an array index equal to the array's size at the very last reference token is not an
|
||||
error there (it becomes a new member or an appended element) instead of
|
||||
[`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403)/[`out_of_range.402`](../../home/exceptions.md#jsonexceptionout_of_range402).
|
||||
For the last reference token itself: if the parent is an object (or a primitive value, where it throws
|
||||
`type_error.305`), throws what 2. throws; if the parent is an array, throws what 3. throws for an index that is
|
||||
out of range, or, for a token that is not a valid array index,
|
||||
[`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`.
|
||||
|
||||
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
|
||||
[`invalid_iterator.202`](../../home/exceptions.md#jsonexceptioninvalid_iterator202) ("view does not belong to this
|
||||
document") if `target`/`object`/`array` is a [discarded](../basic_json_view/is_discarded.md) view or a view of a
|
||||
*different* document (overloads 1-3 only; overload 4 always starts from this document's own [`root()`](root.md)).
|
||||
|
||||
## Complexity
|
||||
|
||||
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).
|
||||
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.
|
||||
|
||||
## 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[]`.
|
||||
|
||||
Setting a member (2.) or an element (3., through 4.) of an array or object whose elements have not been edited
|
||||
before switches it from its parsed layout to a growable block holding links to its elements; a later
|
||||
[`push_back`](push_back.md) or `set` on the same container reuses that block, growing it (amortized constant time)
|
||||
only once it runs out of room. This never moves an element itself -- only where the container's *links* to its
|
||||
elements live -- so a view of an element stays valid, but any iterator already taken over the container is
|
||||
invalidated, since it was walking the old layout. See [Edits](index.md#edits) for what stays valid across an edit in
|
||||
general.
|
||||
|
||||
The same switch happens, for the same reason, when overload 1. replaces a multi-node array/object value with a
|
||||
scalar: the *parent's* element sequence is what has to switch to links, not `target` itself, because the parent
|
||||
originally stepped over `target`'s whole subtree by its node count, which no longer applies once `target` is a
|
||||
one-node scalar.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: (1)/(2)/(3)/(4) replace a value, set a member, assign an element, set via a JSON pointer"
|
||||
|
||||
The example below edits a small configuration document -- replacing a value, adding an object member, assigning
|
||||
an array element, and reaching a field through a JSON pointer -- and shows what
|
||||
[`dump()`](../basic_json_view/dump.md) preserves that is lost once the same edits are made on a `BasicJsonType`
|
||||
value instead: the order object members were written in, and the exact spelling of a number that was never
|
||||
touched.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/basic_json_document__set.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/basic_json_document__set.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [push_back](push_back.md) - append to an array
|
||||
- [insert](insert.md) - insert an element into an array
|
||||
- [erase](erase.md) - remove an object member, an array element, or the value a JSON pointer refers to
|
||||
- [root](root.md) - the view of the root value, the starting point of overload 4
|
||||
- [`basic_json_view::dump`](../basic_json_view/dump.md) - serialize the document, keeping an untouched number's
|
||||
spelling with `#!cpp number_format::source`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
- [Editing a document](../../features/json_view.md#editing-a-document) - why editable documents keep the source
|
||||
text's order and number spelling
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -3,7 +3,7 @@
|
||||
<small>Defined in header `<nlohmann/json_view.hpp>`</small>
|
||||
|
||||
```cpp
|
||||
template<typename BasicJsonType>
|
||||
template<typename BasicJsonType, bool Editable = false>
|
||||
class basic_json_view;
|
||||
```
|
||||
|
||||
@@ -27,16 +27,30 @@ subtree on demand. [`operator[]`](operator%5B%5D.md), [`at`](at.md), [`contains`
|
||||
[`operator!=`](operator_ne.md) compare two views, or a view and a `BasicJsonType` value, without ever building a
|
||||
`BasicJsonType` value for a view; no ordering comparison (`#!cpp operator<`) is provided.
|
||||
|
||||
`basic_json_view` itself is always read-only -- it never has a `set` or `push_back` of its own. A view of an
|
||||
**editable** document (`#!cpp Editable == true`) sees every edit made through
|
||||
[`basic_json_document::set`](../basic_json_document/set.md) and
|
||||
[`basic_json_document::push_back`](../basic_json_document/push_back.md): once a value is changed, every view that
|
||||
still refers to it -- including ones taken before the change -- reads the new value. See
|
||||
[Edits](../basic_json_document/index.md#edits).
|
||||
|
||||
## Template parameters
|
||||
|
||||
`BasicJsonType`
|
||||
: a specialization of [`basic_json`](../basic_json/index.md), matching the
|
||||
[`basic_json_document`](../basic_json_document/index.md) the view was taken from.
|
||||
|
||||
`Editable`
|
||||
: whether the view is of an editable document, matching the [`basic_json_document`](../basic_json_document/index.md)
|
||||
it was taken from (optional, `#!cpp false` by default). See [Edits](../basic_json_document/index.md#edits).
|
||||
|
||||
## Specializations
|
||||
|
||||
- [**json_view**](../json_view.md) - views of a [`json_document`](../json_document.md)
|
||||
- [**ordered_json_view**](../ordered_json_view.md) - views of an [`ordered_json_document`](../ordered_json_document.md)
|
||||
- [**json_editable_view**](../json_editable_view.md) - views of a [`json_editable_document`](../json_editable_document.md)
|
||||
- [**ordered_json_editable_view**](../ordered_json_editable_view.md) - views of an
|
||||
[`ordered_json_editable_document`](../ordered_json_editable_document.md)
|
||||
|
||||
## Member types
|
||||
|
||||
|
||||
43
docs/mkdocs/docs/api/json_editable_document.md
Normal file
43
docs/mkdocs/docs/api/json_editable_document.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# <small>nlohmann::</small>json_editable_document
|
||||
|
||||
<small>Defined in header `<nlohmann/json_view.hpp>`</small>
|
||||
|
||||
```cpp
|
||||
using json_editable_document = basic_json_document<json, true>;
|
||||
```
|
||||
|
||||
This type is an **editable** [`basic_json_document`](basic_json_document/index.md) of the default
|
||||
[`json`](json.md) specialization: in addition to everything [`json_document`](json_document.md) offers,
|
||||
[`set`](basic_json_document/set.md) and [`push_back`](basic_json_document/push_back.md) change values after
|
||||
parsing, without ever rewriting the source text -- see [Edits](basic_json_document/index.md#edits) and
|
||||
[Editing a document](../features/json_view.md#editing-a-document).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below patches two fields of a small configuration document -- changing one and adding another --
|
||||
and dumps it back out with the member order and the spelling of the untouched number preserved, something a
|
||||
plain [`json`](json.md) value cannot do.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_editable_document.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/json_editable_document.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [json_editable_view](json_editable_view.md) - a view of a value of a `json_editable_document`
|
||||
- [json_document](json_document.md) - the read-only document this type adds edits to
|
||||
- [ordered_json_editable_document](ordered_json_editable_document.md) - the corresponding editable document for
|
||||
`ordered_json`
|
||||
- [Edits](basic_json_document/index.md#edits) - what an edit guarantees
|
||||
|
||||
## Version history
|
||||
|
||||
Since version 3.13.0.
|
||||
41
docs/mkdocs/docs/api/json_editable_view.md
Normal file
41
docs/mkdocs/docs/api/json_editable_view.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# <small>nlohmann::</small>json_editable_view
|
||||
|
||||
<small>Defined in header `<nlohmann/json_view.hpp>`</small>
|
||||
|
||||
```cpp
|
||||
using json_editable_view = basic_json_view<json, true>;
|
||||
```
|
||||
|
||||
This type is a [`basic_json_view`](basic_json_view/index.md) of a value of a
|
||||
[`json_editable_document`](json_editable_document.md). It offers the same read-only interface as
|
||||
[`json_view`](json_view.md); what is different is what it can be a view *of* -- a value that
|
||||
[`set`](basic_json_document/set.md) and [`push_back`](basic_json_document/push_back.md) can change, with every view
|
||||
still referring to it seeing the change, see [Edits](basic_json_document/index.md#edits).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below is the same as [`json_editable_document`'s](json_editable_document.md): every view read back
|
||||
out of the document -- `#!cpp doc.root()` and the views nested under it -- sees the edits made through `set`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_editable_document.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/json_editable_document.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [json_editable_document](json_editable_document.md) - the document type this view refers into
|
||||
- [json_view](json_view.md) - the corresponding read-only view
|
||||
- [ordered_json_editable_view](ordered_json_editable_view.md) - the corresponding view for
|
||||
`ordered_json_editable_document`
|
||||
|
||||
## Version history
|
||||
|
||||
Since version 3.13.0.
|
||||
47
docs/mkdocs/docs/api/ordered_json_editable_document.md
Normal file
47
docs/mkdocs/docs/api/ordered_json_editable_document.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# <small>nlohmann::</small>ordered_json_editable_document
|
||||
|
||||
<small>Defined in header `<nlohmann/json_view.hpp>`</small>
|
||||
|
||||
```cpp
|
||||
using ordered_json_editable_document = basic_json_document<ordered_json, true>;
|
||||
```
|
||||
|
||||
This type is an **editable** [`basic_json_document`](basic_json_document/index.md) of the
|
||||
[`ordered_json`](ordered_json.md) specialization: [`set`](basic_json_document/set.md) and
|
||||
[`push_back`](basic_json_document/push_back.md) change values after parsing, as for
|
||||
[`json_editable_document`](json_editable_document.md), and
|
||||
[`materialize()`](basic_json_view/materialize.md) preserves the document order of object members -- including
|
||||
members [`set`](basic_json_document/set.md) added -- instead of sorting them like
|
||||
[`json_editable_document`](json_editable_document.md) does.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below edits a document with `set`, then shows that `materialize()` keeps the member order of the
|
||||
source text (with the new member at the end) for `ordered_json_editable_document`, where it would sort the
|
||||
members alphabetically for [`json_editable_document`](json_editable_document.md).
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_json_editable_document.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/ordered_json_editable_document.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [ordered_json_editable_view](ordered_json_editable_view.md) - a view of a value of an
|
||||
`ordered_json_editable_document`
|
||||
- [ordered_json_document](ordered_json_document.md) - the read-only document this type adds edits to
|
||||
- [json_editable_document](json_editable_document.md) - the corresponding editable document for the default `json`
|
||||
specialization
|
||||
- [Object Order](../features/object_order.md)
|
||||
- [Edits](basic_json_document/index.md#edits) - what an edit guarantees
|
||||
|
||||
## Version history
|
||||
|
||||
Since version 3.13.0.
|
||||
40
docs/mkdocs/docs/api/ordered_json_editable_view.md
Normal file
40
docs/mkdocs/docs/api/ordered_json_editable_view.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# <small>nlohmann::</small>ordered_json_editable_view
|
||||
|
||||
<small>Defined in header `<nlohmann/json_view.hpp>`</small>
|
||||
|
||||
```cpp
|
||||
using ordered_json_editable_view = basic_json_view<ordered_json, true>;
|
||||
```
|
||||
|
||||
This type is a [`basic_json_view`](basic_json_view/index.md) of a value of an
|
||||
[`ordered_json_editable_document`](ordered_json_editable_document.md), the corresponding view for
|
||||
[`ordered_json_view`](ordered_json_view.md) the way [`json_editable_view`](json_editable_view.md) is for
|
||||
[`json_view`](json_view.md).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example below is the same as [`ordered_json_editable_document`'s](ordered_json_editable_document.md): the
|
||||
views `set` returns see the document's member order preserved on `materialize()`, unlike for a
|
||||
[`json_editable_document`](json_editable_document.md).
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/ordered_json_editable_document.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/ordered_json_editable_document.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [ordered_json_editable_document](ordered_json_editable_document.md) - the document type this view refers into
|
||||
- [ordered_json_view](ordered_json_view.md) - the corresponding read-only view
|
||||
- [json_editable_view](json_editable_view.md) - the corresponding view for `json_editable_document`
|
||||
|
||||
## Version history
|
||||
|
||||
Since version 3.13.0.
|
||||
Reference in New Issue
Block a user