* json_view: view_mode enum instead of bool Editable, node_kind for node::kind basic_json_document and basic_json_view take a view_mode (read_only, the default, or editable) instead of a bool: basic_json_document<json, true> did not say what true means. The shortcut aliases are unchanged. The kind of a node is a node_kind (the value_t values plus link, 10 as before), which removes the static_cast<std::uint8_t>(value_t::...) of every comparison. The node and image layouts are unchanged. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * json_view: node_kind in the node writers, spell out read_only, comment fixes The builder and the edit functions take and store a node_kind instead of casting a value_t; the numbering assertions and the comments now speak of node_kind, and the link kind notes that it follows value_t::discarded. The read-only aliases name view_mode::read_only like the editable ones. view_mode.md says the mode is a compile-time property of the type. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * json_view: views of read-only documents convert to editable views A read-only document has no edits, so a view of it reads correctly as a view of an editable document before its first edit. The implicit conversion lets a function taking a json_editable_view accept the views of both modes. There is no conversion the other way: a read-only view of an editable document would read wrong values after the next edit. The mode comparisons in the cross-mode operator==/!= use an is_other_mode trait, which astyle keeps compact. Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
4.7 KiB
nlohmann::basic_json_document::save
std::vector<std::uint8_t> save() const;
Writes the document as an image: a byte buffer that load reads back without parsing. The image holds
the node index, the source text (plus, for an edited document, the number tokens edits wrote), and the decoded
strings (plus the strings edits wrote) -- everything root() needs, with nothing left to parse.
An edited document is written in its current state, with its values in document order, the way the library's own
parser would have produced them for that JSON text: a member set added goes at the end, an
erased member leaves no trace, and a float that is not finite (NaN or positive/negative infinity)
becomes null, the same substitution dump() makes. The same document always saves to
the same bytes -- also across BasicJsonType and the view_mode, since the image reflects document order and
values only, not which specialization produced them.
Return value
The image, as a #!cpp std::vector<std::uint8_t>. Pass it, or a pointer to its data together with its size, to
load to read the document back.
Exception safety
Strong guarantee: save() does not modify #!cpp *this (it is #!cpp const), so if it throws, the document is left
exactly as it was, and the partially built image is discarded with the exception.
Exceptions
Throws type_error.320 if the document is
discarded -- a default-constructed document, or one a failed parse()/
read() with allow_exceptions == false left discarded.
On a big-endian target, throws type_error.320 with a different message instead: the image format is little-endian
only (see Notes).
Throws out_of_range.416 if the node count, the text, or
the decoded strings of the image would individually reach 4 GiB -- the same 32-bit offsets
parse() and, for edits, set/push_back are already limited to.
!!! failure "Example messages"
```
[json.exception.type_error.320] cannot save a discarded json_document
```
```
[json.exception.type_error.320] json_document images need a little-endian target
```
```
[json.exception.out_of_range.416] images of 4 GiB or more are not supported by json_document
```
Complexity
Linear in the size of the document: the number of nodes, plus the length of the text and the decoded strings that end up in the image.
Notes
Format. The image begins with a 64-byte header (the magic bytes #!cpp "NJVI", a version number, the node count,
and the sizes of the text and the decoded strings, all little-endian), followed by the nodes
(16 bytes each), the text and a #!cpp '\0', and the decoded
strings and a #!cpp '\0'. load checks the header, and the sizes it describes, before reading anything
else -- see load's Exceptions.
!!! warning "Experimental"
The image format is versioned but not yet stable: it may change in an incompatible way before it is declared
stable. Use images to cache a document within one build of the library, or to hand one to another process running
the *same* build on the *same* (little-endian) machine -- not as a long-term storage format. Keep the original
JSON text if you need to read a saved document back with a future library version.
Little-endian only. The image is written as raw little-endian bytes, with no byte-swapping. save() (and
load) throw type_error.320 on a big-endian target rather than silently produce bytes a big-endian
reader could not interpret correctly.
Examples
??? example "Caching a parsed document as an image"
The example below saves a parsed configuration as an image -- the way a service might cache one to answer later
requests without parsing the text again -- and confirms that loading it back gives exactly the same result as
parsing did, and that saving is deterministic.
```cpp
--8<-- "examples/basic_json_document__save.cpp"
```
Output:
```json
--8<-- "examples/basic_json_document__save.output"
```
See also
- load - read an image written by
save() - owns_source - return whether the document holds its own copy of the text
basic_json_view::dump- serialize the document to JSON text instead of an image- Images - why and when to use images
Version history
- Added in version 3.13.0.