* Split the json_view feature page into sub-pages
The single features/json_view.md page grew to ~600 lines covering eight
topics. Split it into features/json_view/ with an overview page and
pages for ownership and lifetime, differences from basic_json, reading
values, generic code, editing, and images.
The new differences page collects what was spread over several sections
("What is the same", "What is different", "Duplicate keys", and notes in
the conversion and serialization sections) under one summary table, and
adds the parts of the basic_json interface a view does not have. The
other pages now link to it instead of restating the rules.
Internal links across the documentation point to the new pages.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Docs: fix stale comments and trim repeated text in json_view pages
- fig-jsonview.js/.css: point the header comments at the new pages
- reading.md: views' strings are valid as long as the document (and a
borrowed source text), as lifetime.md says
- reading.md, generic_code.md: link to differences.md instead of
restating the member-order and repeated-key rules
- differences.md: drop the third mention of ordering comparisons, name
rbegin()/rend() in the iterator row
- exceptions.md: link editable documents to editing.md
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
---------
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
8.3 KiB
Editing a document
A json_document/json_view lets you look at a parsed text
without copying it, but not change it.
basic_json_document<BasicJsonType, view_mode::editable> — more
conveniently spelled json_editable_document or
ordered_json_editable_document — also lets you
set a value, push_back onto
or insert into an array, and
erase an object member or an array element, still without ever building a
basic_json tree for parts you do not touch.
The mode defaults to #!cpp view_mode::read_only, so
json_document/ordered_json_document are unaffected — they carry 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
A price like #!cpp 19.90 is exactly the kind of value that makes editing a json or ordered_json value in place
lossy. Say you parse a configuration file, patch one field, and write it back:
jsonre-sorts every key on the way in (object_tis a#!cpp std::map) and rewrites every number to its shortest round-trip form on the way out — a one-field patch turns into a diff that reorders the whole file and rewrites#!cpp 19.90to#!cpp 19.9.ordered_jsonkeeps the key order, but still rewrites every number the same way: parsing has already reduced it to a#!cpp double/#!cpp int64_t, and there is no way back to how it was spelled in the source text.
The patch of the example below (set "host", add "retries") written back by each of them:
json
keys sorted, numbers rewritten
{"host":"db2",
"name":"cache",
"port":6379,
"price":19.9,
"retries":3}ordered_json
key order kept, numbers rewritten
{"name":"cache",
"host":"db2",
"port":6379,
"price":19.9,
"retries":3}json_editable_document
order and spelling kept
{"name":"cache",
"host":"db2",
"port":6379,
"price":19.90,
"retries":3}An editable document keeps both. dump() of an edited document writes members in
document order — a member set added goes at the end, exactly where it was
inserted, and an erased member simply leaves a gap: everything around it
keeps its place — and number_format::source 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() would write it, since there is no source spelling for a brand
new value. See Writing a view back.
??? example "Example: patch a configuration, keeping member order and number spellings"
```cpp
--8<-- "examples/json_editable_document.cpp"
```
Output:
```json
--8<-- "examples/json_editable_document.output"
```
What stays valid, and what an edit costs
The source text itself is never written, and the parsed index never moves — a value keeps the node it was
parsed into for as long as it is not itself replaced. So every view taken before
an edit, including a previously obtained root(), 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 an element is added to it,
inserted into it, erased from it, or replaced by a value that spans a different number of nodes, its elements move
from the parsed, fixed layout to a growable block of links so that
push_back 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() is unaffected either way and stays valid across further
edits. See basic_json_document's Edits for the details, and
set's Exception safety for what an edit guarantees if it
throws (the basic guarantee, not the strong one dump() and the read-only functions provide). How edits are kept in
the index is described in the architecture overview.
Step through the edits of a small document (the node fields follow the architecture overview):
doc.set(doc.root(), "port", 6380) overwrites the node of the integer in place; no member is added or removed, so the object keeps its parsed layout.doc.erase(doc.root()["tags"], 0): the array is edited for the first time, so its elements move to a block of links in owned storage. The node of "eu" stays in the index, but nothing refers to it any more; iterators over the array taken before are invalid.doc.push_back(doc.root()["tags"], "new"): the new string gets its own node, its text goes to the buffer of edited text, and a link to it is appended to the block of the array.doc.set(doc.root(), "retries", 3): a new member, so the object moves to a block too: copies of its keys, links to the values it already had, then the new key and a link to the new integer.The node index and the owned storage of the document after each of five edits. Use *Back*, *Next*, or the numbered buttons to switch between the steps; without JavaScript all steps are shown one below the other.
See also
- Zero-copy JSON views - overview
json_editable_document- andordered_json_editable_document- the documents that can be edited in placebasic_json_document's Edits - the rules of edits in detail- Differences from
basic_json- source positions after edits
Version history
- Added in version 3.13.0.