| # <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 view_mode::editable`, 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. 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 | |
| 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. 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 | |
| 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); 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 | |
| [`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 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; 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[]`. | |
| 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 | |
| #include <iostream> | |
| #include <nlohmann/json_view.hpp> | |
| using nlohmann::json; | |
| using nlohmann::json_editable_document; | |
| using nlohmann::json_editable_view; | |
| int main() | |
| { | |
| // a configuration file, as it might be read from disk -- "price" is | |
| // written with a trailing zero that has no effect on its value | |
| const std::string text = R"({ | |
| "name": "cache", | |
| "host": "db1", | |
| "port": 6379, | |
| "price": 19.90, | |
| "replicas": ["db2", "db3"], | |
| "timeout": 30 | |
| })"; | |
| json_editable_document doc = json_editable_document::parse(text); | |
| doc.set(doc.root()["port"], 6380); // (1) replace a value | |
| doc.set(doc.root(), "region", "us-east"); // (2) add a member | |
| doc.set(doc.root()["replicas"], 0, "db4"); // (3) assign an element | |
| doc.set(json::json_pointer("/timeout"), 45); // (4) via a JSON pointer | |
| // members stay in document order (the new one at the end), and a number | |
| // that was not itself edited keeps its exact spelling | |
| std::cout << doc.root().dump(2, ' ', false, json_editable_view::number_format::source) << "\n\n"; | |
| // the same edits on a plain json value: object_t is a std::map, so | |
| // parsing already sorted the keys, and dump() rewrites every number to | |
| // its shortest form, even "price", which was never touched | |
| json plain = json::parse(text); | |
| plain["port"] = 6380; | |
| plain["region"] = "us-east"; | |
| plain["replicas"][0] = "db4"; | |
| plain[json::json_pointer("/timeout")] = 45; | |
| std::cout << plain.dump(2) << '\n'; | |
| } | |
| ``` | |
| Output: | |
| ```json | |
| { | |
| "name": "cache", | |
| "host": "db1", | |
| "port": 6380, | |
| "price": 19.90, | |
| "replicas": [ | |
| "db4", | |
| "db3" | |
| ], | |
| "timeout": 45, | |
| "region": "us-east" | |
| } | |
| { | |
| "host": "db1", | |
| "name": "cache", | |
| "port": 6380, | |
| "price": 19.9, | |
| "region": "us-east", | |
| "replicas": [ | |
| "db4", | |
| "db3" | |
| ], | |
| "timeout": 45 | |
| } | |
| ``` | |
| ## 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. |