diff --git a/docs/docset/docSet.sql b/docs/docset/docSet.sql index ee2f3c95a..42b92757c 100644 --- a/docs/docset/docSet.sql +++ b/docs/docset/docSet.sql @@ -131,6 +131,8 @@ INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::~basic_json', 'Me INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document', 'Class', 'api/basic_json_document/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document::basic_json_document', 'Constructor', 'api/basic_json_document/basic_json_document/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document::accept', 'Function', 'api/basic_json_document/accept/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document::erase', 'Method', 'api/basic_json_document/erase/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document::insert', 'Method', 'api/basic_json_document/insert/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document::is_discarded', 'Method', 'api/basic_json_document/is_discarded/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document::memory_usage', 'Method', 'api/basic_json_document/memory_usage/index.html'); INSERT INTO searchIndex(name, type, path) VALUES ('basic_json_document::node_count', 'Method', 'api/basic_json_document/node_count/index.html'); diff --git a/docs/mkdocs/docs/api/basic_json_document/erase.md b/docs/mkdocs/docs/api/basic_json_document/erase.md new file mode 100644 index 000000000..cbdc79765 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json_document/erase.md @@ -0,0 +1,128 @@ +# nlohmann::basic_json_document::erase + +```cpp +// (1) +std::size_t erase(view_type object, string_view_t key); + +// (2) +template +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. diff --git a/docs/mkdocs/docs/api/basic_json_document/index.md b/docs/mkdocs/docs/api/basic_json_document/index.md index a5ffbe73a..534b63755 100644 --- a/docs/mkdocs/docs/api/basic_json_document/index.md +++ b/docs/mkdocs/docs/api/basic_json_document/index.md @@ -19,10 +19,10 @@ 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) and [`push_back`](push_back.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 `set` or -`push_back` on one fails to compile (`#!cpp static_assert`). +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 @@ -32,8 +32,8 @@ values in place, see [Edits](#edits) below. The source text itself is never writ is checked with a `static_assert`. `Editable` -: whether the document supports [`set`](set.md) and [`push_back`](push_back.md) (optional, `#!cpp false` by - default). See [Edits](#edits) below. +: 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 @@ -66,11 +66,15 @@ values in place, see [Edits](#edits) below. The source text itself is never writ - [**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) and -[`push_back`](push_back.md); [`json_editable_document`](../json_editable_document.md) and +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: diff --git a/docs/mkdocs/docs/api/basic_json_document/insert.md b/docs/mkdocs/docs/api/basic_json_document/insert.md new file mode 100644 index 000000000..b513dfc0d --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json_document/insert.md @@ -0,0 +1,114 @@ +# nlohmann::basic_json_document::insert + +```cpp +template +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. diff --git a/docs/mkdocs/docs/api/basic_json_document/push_back.md b/docs/mkdocs/docs/api/basic_json_document/push_back.md index b50f6a347..37ce10bc5 100644 --- a/docs/mkdocs/docs/api/basic_json_document/push_back.md +++ b/docs/mkdocs/docs/api/basic_json_document/push_back.md @@ -91,6 +91,8 @@ Like [`set`](set.md) on a member or an element, `push_back` never moves an exist ## 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 diff --git a/docs/mkdocs/docs/api/basic_json_document/set.md b/docs/mkdocs/docs/api/basic_json_document/set.md index 3741cf44a..f9d73b94c 100644 --- a/docs/mkdocs/docs/api/basic_json_document/set.md +++ b/docs/mkdocs/docs/api/basic_json_document/set.md @@ -180,6 +180,8 @@ one-node scalar. ## 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` diff --git a/docs/mkdocs/docs/examples/basic_json_document__erase.cpp b/docs/mkdocs/docs/examples/basic_json_document__erase.cpp new file mode 100644 index 000000000..4b3197698 --- /dev/null +++ b/docs/mkdocs/docs/examples/basic_json_document__erase.cpp @@ -0,0 +1,38 @@ +#include +#include + +using json = nlohmann::json; +using json_editable_document = nlohmann::json_editable_document; +using json_editable_view = nlohmann::json_editable_view; + +int main() +{ + // a deprecated field is dropped from a configuration file, and a + // decommissioned replica is removed from the list -- "price" keeps its + // trailing zero, and the fields around the removed ones keep their order + const std::string text = R"({ + "name": "cache", + "legacy_host": "db0", + "host": "db1", + "price": 19.90, + "replicas": ["db2", "db3", "db4"] +})"; + + json_editable_document doc = json_editable_document::parse(text); + + doc.erase(doc.root(), "legacy_host"); // (1) an object member + doc.erase(doc.root()["replicas"], 1); // (2) an array element ("db3") + const std::size_t removed = doc.erase(json::json_pointer("/replicas/0")); // (3) via a JSON pointer + + std::cout << removed << '\n'; + 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.erase("legacy_host"); + plain["replicas"].erase(1); + plain["replicas"].erase(0); + std::cout << plain.dump(2) << '\n'; +} diff --git a/docs/mkdocs/docs/examples/basic_json_document__erase.output b/docs/mkdocs/docs/examples/basic_json_document__erase.output new file mode 100644 index 000000000..de764877a --- /dev/null +++ b/docs/mkdocs/docs/examples/basic_json_document__erase.output @@ -0,0 +1,18 @@ +1 +{ + "name": "cache", + "host": "db1", + "price": 19.90, + "replicas": [ + "db4" + ] +} + +{ + "host": "db1", + "name": "cache", + "price": 19.9, + "replicas": [ + "db4" + ] +} diff --git a/docs/mkdocs/docs/examples/basic_json_document__insert.cpp b/docs/mkdocs/docs/examples/basic_json_document__insert.cpp new file mode 100644 index 000000000..1c04bd6cc --- /dev/null +++ b/docs/mkdocs/docs/examples/basic_json_document__insert.cpp @@ -0,0 +1,38 @@ +#include +#include + +using json = nlohmann::json; +using json_editable_document = nlohmann::json_editable_document; +using json_editable_view = nlohmann::json_editable_view; + +int main() +{ + // a deployment plan -- "budget" is written with a trailing zero that has + // no effect on its value + const std::string text = R"({ + "release": "2026.09", + "steps": ["build", "test", "deploy"], + "budget": 19.90 +})"; + + json_editable_document doc = json_editable_document::parse(text); + + const std::size_t deploy_index = 2; + const auto deploy = doc.root()["steps"][deploy_index]; // held across the insert + + doc.insert(doc.root()["steps"], deploy_index, "smoke-test"); // insert before "deploy" + + // the held view still refers to "deploy", even though its index moved + // from 2 to 3, and nothing else in the document was touched + std::cout << deploy.dump() << '\n'; + std::cout << doc.root().dump(2, ' ', false, json_editable_view::number_format::source) << "\n\n"; + + // the same edit on a plain json value: an index held from before the + // insert now refers to whatever moved into that slot, and dump() + // rewrites "budget" to its shortest form even though it was never + // touched + json plain = json::parse(text); + plain["steps"].insert(plain["steps"].begin() + static_cast(deploy_index), "smoke-test"); + std::cout << plain["steps"][deploy_index].dump() << '\n'; + std::cout << plain.dump(2) << '\n'; +} diff --git a/docs/mkdocs/docs/examples/basic_json_document__insert.output b/docs/mkdocs/docs/examples/basic_json_document__insert.output new file mode 100644 index 000000000..1b2480df1 --- /dev/null +++ b/docs/mkdocs/docs/examples/basic_json_document__insert.output @@ -0,0 +1,23 @@ +"deploy" +{ + "release": "2026.09", + "steps": [ + "build", + "test", + "smoke-test", + "deploy" + ], + "budget": 19.90 +} + +"smoke-test" +{ + "budget": 19.9, + "release": "2026.09", + "steps": [ + "build", + "test", + "smoke-test", + "deploy" + ] +} diff --git a/docs/mkdocs/docs/features/json_view.md b/docs/mkdocs/docs/features/json_view.md index f67fe5160..8a275db4a 100644 --- a/docs/mkdocs/docs/features/json_view.md +++ b/docs/mkdocs/docs/features/json_view.md @@ -193,11 +193,13 @@ Everything above is read-only: a `json_document`/`json_view` lets you look at a not change it. [`basic_json_document`](../api/basic_json_document/index.md) -- more conveniently spelled [`json_editable_document`](../api/json_editable_document.md) or [`ordered_json_editable_document`](../api/ordered_json_editable_document.md) -- also lets you -[`set`](../api/basic_json_document/set.md) a value and [`push_back`](../api/basic_json_document/push_back.md) onto -an array, still without ever building a `basic_json` tree for parts you do not touch. +[`set`](../api/basic_json_document/set.md) a value, [`push_back`](../api/basic_json_document/push_back.md) onto or +[`insert`](../api/basic_json_document/insert.md) into an array, and [`erase`](../api/basic_json_document/erase.md) +an object member or an array element, still without ever building a `basic_json` tree for parts you do not touch. `#!cpp Editable` defaults to `#!cpp false`, so `json_document`/`ordered_json_document` are unaffected -- they carry -none of the bookkeeping edits need, and calling `set`/`push_back` on one is a compile error, not a runtime one. +none of the bookkeeping edits need, and calling `set`/`push_back`/`insert`/`erase` on one is a compile error, not a +runtime one. ### Why: editing without reformatting @@ -212,8 +214,9 @@ or `ordered_json` value in place lossy. Say you parse a configuration file, patc An editable document keeps both. [`dump()`](../api/basic_json_view/dump.md) of an edited document writes members in document order -- a member [`set`](../api/basic_json_document/set.md) added goes at the end, exactly where it was -inserted -- and [`number_format::source`](../api/basic_json_view/number_format.md) keeps the exact spelling of -every number an edit did not itself touch; a number an edit *did* touch is written the way +inserted, and an [`erase`](../api/basic_json_document/erase.md)d member simply leaves a gap: everything around it +keeps its place -- and [`number_format::source`](../api/basic_json_view/number_format.md) keeps the exact spelling +of every number an edit did not itself touch; a number an edit *did* touch is written the way [`BasicJsonType::dump()`](../api/basic_json/dump.md) would write it, since there is no source spelling for a brand new value. @@ -236,10 +239,11 @@ parsed into for as long as it is not itself replaced. So every [view](../api/bas an edit, including a previously obtained [`root()`](../api/basic_json_document/root.md), stays valid and, if it still refers to the edited value, sees the edit; a view of a value a later edit drops or replaces just keeps showing what it last held. New values go to storage the document allocates and owns on demand. The one thing an edit does -invalidate is the **iterators** taken over an edited array or object: the first time one of its elements is set or -appended to, its elements move from the parsed, fixed layout to a growable block of links so that -[`push_back`](../api/basic_json_document/push_back.md) can later grow it in amortized constant time -- existing -elements are not touched, but an iterator that was walking the old layout no longer matches. A string obtained with +invalidate is the **iterators** taken over an edited array or object: the first time one of its elements is set, +appended to, inserted into, or erased, its elements move from the parsed, fixed layout to a growable block of links +so that [`push_back`](../api/basic_json_document/push_back.md) can later grow it in amortized constant time -- +existing elements are not touched, but an iterator that was walking the old layout no longer matches. A string +obtained with [`get_string()`](../api/basic_json_view/get_string.md) is unaffected either way and stays valid across further edits. See [`basic_json_document`'s Edits](../api/basic_json_document/index.md#edits) for the details, and [`set`'s Exception safety](../api/basic_json_document/set.md#exception-safety) for what an edit guarantees if it @@ -251,7 +255,7 @@ the index is described in the [architecture overview](../home/architecture.md#no | | [`json`](../api/json.md) / [`ordered_json`](../api/ordered_json.md) | [SAX interface](parsing/sax_interface.md) | [`json_document`](../api/json_document.md) / [`json_view`](../api/json_view.md) | [`json_editable_document`](../api/json_editable_document.md) / [`json_editable_view`](../api/json_editable_view.md) | |---|---|---|---|---| | **Ownership** | owns every value | owns nothing; you decide what to keep, in your handler | borrows or owns the *text*; the index is always owned by the document | same as `json_document`; edits go to storage the document owns | -| **Mutability** | freely mutable | not applicable (a one-shot event stream) | read-only | [`set`](../api/basic_json_document/set.md)/[`push_back`](../api/basic_json_document/push_back.md) edit in place; the source text is never rewritten | +| **Mutability** | freely mutable | not applicable (a one-shot event stream) | read-only | [`set`](../api/basic_json_document/set.md)/[`push_back`](../api/basic_json_document/push_back.md)/[`insert`](../api/basic_json_document/insert.md)/[`erase`](../api/basic_json_document/erase.md) edit in place; the source text is never rewritten | | **What you get** | a full tree you can read, write, and keep as long as you like | a sequence of callbacks; whatever your handler builds from them | a flat index plus, on demand, [`materialize()`](../api/basic_json_view/materialize.md)d `json`/`ordered_json` values for the parts you actually use | the same, plus [`dump()`](../api/basic_json_view/dump.md) of an edited document that keeps the member order and, with [`number_format::source`](../api/basic_json_view/number_format.md), the spelling of every untouched number | | **Typical use** | general-purpose JSON handling: config, request/response bodies you build or modify, anything you hold onto | validating or projecting a text into your own data structure without ever holding the whole thing as JSON | large or high-volume input where you only need part of it, or need it repeatedly, and can keep the source text (or a copy) alive for as long as the document lives | a document you read, patch a few fields of, and write back -- a configuration file, for instance -- where the rest of it should come back exactly as it was | diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index 58c3abf36..462fddb34 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -233,6 +233,8 @@ nav: - 'Overview': api/basic_json_document/index.md - '(Constructor)': api/basic_json_document/basic_json_document.md - 'accept': api/basic_json_document/accept.md + - 'erase': api/basic_json_document/erase.md + - 'insert': api/basic_json_document/insert.md - 'is_discarded': api/basic_json_document/is_discarded.md - 'memory_usage': api/basic_json_document/memory_usage.md - 'node_count': api/basic_json_document/node_count.md