138 lines
5.9 KiB
Markdown
138 lines
5.9 KiB
Markdown
# <small>nlohmann::basic_json_document::</small>save
|
|
|
|
```cpp
|
|
std::vector<std::uint8_t> save() const;
|
|
```
|
|
|
|
Writes the document as an *image*: a byte buffer that [`load`](load.md) 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()`](root.md) 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`](set.md) added goes at the end, an
|
|
[`erase`](erase.md)d member leaves no trace, and a float that is not finite (NaN or positive/negative infinity)
|
|
becomes null, the same substitution [`dump()`](../basic_json_view/dump.md) makes. The same document always saves to
|
|
the same bytes -- also across `BasicJsonType` and `#!cpp Editable`, 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`](load.md) 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`](../../home/exceptions.md#jsonexceptiontype_error320) if the document is
|
|
[discarded](is_discarded.md) -- a default-constructed document, or one a failed [`parse()`](parse.md)/
|
|
[`read()`](read.md) 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](#notes)).
|
|
|
|
Throws [`out_of_range.416`](../../home/exceptions.md#jsonexceptionout_of_range416) if the node count, the text, or
|
|
the decoded strings of the image would individually reach 4 GiB -- the same 32-bit offsets
|
|
[`parse()`](parse.md#exceptions) and, for edits, [`set`](set.md)/[`push_back`](push_back.md) 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](../../home/architecture.md#node-index-of-json-views)), the text and a `#!cpp '\0'`, and the decoded
|
|
strings and a `#!cpp '\0'`. [`load`](load.md) checks the header, and the sizes it describes, before reading anything
|
|
else -- see [`load`'s Exceptions](load.md#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`](load.md)) 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
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <nlohmann/json_view.hpp>
|
|
|
|
using json_document = nlohmann::json_document;
|
|
|
|
int main()
|
|
{
|
|
std::cout << std::boolalpha;
|
|
|
|
// a configuration a service parses once and then caches as an image, so
|
|
// that later requests can load() it instead of parsing the text again
|
|
const std::string text = R"({"name": "cache", "host": "db1", "port": 6379, "replicas": ["db2", "db3"]})";
|
|
const json_document config = json_document::parse(text);
|
|
|
|
// save() turns the parsed document into a byte buffer: a 64-byte header,
|
|
// the node index, the source text, and the decoded strings
|
|
const std::vector<std::uint8_t> image = config.save();
|
|
std::cout << image.size() << '\n';
|
|
|
|
// the same document always saves to the same bytes
|
|
std::cout << (image == json_document::parse(text).save()) << '\n';
|
|
|
|
// loading the image back needs no parsing, yet dumps exactly what
|
|
// parsing the text produced
|
|
const json_document reloaded = json_document::load(image);
|
|
std::cout << (reloaded.root().dump() == config.root().dump()) << '\n';
|
|
}
|
|
|
|
```
|
|
|
|
Output:
|
|
|
|
```json
|
|
316
|
|
true
|
|
true
|
|
|
|
```
|
|
|
|
## See also
|
|
|
|
- [load](load.md) - read an image written by `save()`
|
|
- [owns_source](owns_source.md) - return whether the document holds its own copy of the text
|
|
- [`basic_json_view::dump`](../basic_json_view/dump.md) - serialize the document to JSON text instead of an image
|
|
- [Images](../../features/json_view.md#images) - why and when to use images
|
|
|
|
## Version history
|
|
|
|
- Added in version 3.13.0.
|