rapidyaml 0.15.2
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
How to use (de)serialization

Shows basic use of the calls to serialize and deserialize.

Shows basic use of the calls to serialize and deserialize.

The top-level serialization functions are NodeRef::save() / ConstNodeRef::load() to deserialize, and its tree equivalents Tree::save() / Tree::load():

See also
sample_serialize_basic()
Serialization of user types to implement for user types
ryml::NodeRef node = ...;
// serialize
node.save(42);
CHECK(node.val() == "42");
// deserialize
int answer = 0;
node.load(&answer);
CHECK(answer == 42);
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
Definition node.hpp:1063
void save(T const &k)
Definition node.hpp:1337
#define CHECK(predicate)
a testing assertion, used only in this quickstart
csubstr val() const RYML_NOEXCEPT
Forward to Tree::val().
Definition node.hpp:179
void load(T *v, bool check_readable=true) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
Definition node.hpp:345

or, if you prefer the tree API,

ryml::id_type node_id = ...;
// serialize
tree.save(node_id, 42);
CHECK(tree.val(node_id) == "42");
// deserialize
int answer = 0;
tree.load(node_id, &answer);
CHECK(answer == 42);
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
Definition common.hpp:124

The functions for serializing keys are NodeRef::save_key() to serialize and ConstNodeRef::load_key() to deserialize, and its tree equivalents Tree::save_key() and Tree::load_key(). But note that the Tree cannot handle container keys, so they must serialized as a scalar.



Setting styles while serializing

When serializing scalars, it is advised to set explicit scalar styles when building a tree for subsequently emitting. This is because YAML has constraints on which styles can be used for a particular scalar.

When the scalar is not marked with an explicit style, the ryml emitter adheres to these constraints at run time by scanning each scalar to choose a style for it. On the other hand, if the scalar is marked with an explicit style, the emitter does not have to do the scan.

So explicitly setting the style saves the emitter from having to scan each scalar while emitting.

ryml::Tree tree = parse_in_arena("map:");
ryml::NodeRef map = tree["map"];
// serialize with explicit style
map["single quoted"].save("scalar", ryml::VAL_PLAIN);
map["single quoted"].save("scalar", ryml::VAL_SQUO);
map["double quoted"].save("scalar", ryml::VAL_DQUO);
map["literal"].save("scalar", ryml::VAL_LITERAL);
map["folded"].save("scalar", ryml::VAL_FOLDED);
"map:\n"
"plain: scalar\n"
"single quoted: 'scalar'\n"
"double quoted: \"scalar\"\n"
"literal: |-\n
" \"scalar\"\n"
"folded: >-\n
" \"scalar\"\n"
);
substr emitrs_yaml(Tree const &t, id_type id, EmitOptions const &opts, CharOwningContainer *cont, bool append=false)
(1) emit+resize: emit YAML to the given std::string/std::vector<char>-like container,...
@ VAL_FOLDED
mark val scalar as multiline, block folded >
@ VAL_SQUO
mark val scalar as single quoted '
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
@ VAL_DQUO
mark val scalar as double quoted "
@ VAL_LITERAL
mark val scalar as multiline, block literal |
void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *tree, id_type node_id)
(1) parse YAML into an existing tree node. The filename will be used in any error messages arising du...
Definition parse.cpp:209

The optional style parameter can and should be also used with all the tree building functions (eg, NodeRef::set_val(), etc).



Checks: .load() vs .deserialize()

.load() does a lot of hand-holding to ensure the preconditions are met before attempting to read from the node, and it then checks the success of the deserialization, triggering an error if anything is wrong. To be clear, these are checks and not assertions, so they are done regardless of build type.

This results generally in safer user code, but comes at a slight cost. You can avoid this cost, if you wish. First, .load() has a parameter that turns the readability check into an assertion, but keeps the deserialization check:

ryml::ConstNodeRef node = ...;
node.load(&answer, false); // disable readability check
Holds a pointer to an existing tree, and a node id.
Definition node.hpp:737

or, if you prefer the tree API

ryml::Tree tree = ...;
ryml::id_type node_id = ...;
bool check_readable = false
tree.load(node_id, &answer, check_readable); // assumes the node is ok
void load(id_type node, T *v, bool check_readable=true) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
Definition tree.hpp:871

And further, you can avoid exceptional flow in the code by using instead ConstNodeRef::deserialize() or Tree::deserialize(). These functions attempt to deserialize and return a [[nodiscard]] boolean with the deserialization status:

ryml::ConstNodeRef node = ...;
if(... node is ok ...)
if(!node.deserialize(&answer))
... // deserialization failed, react accordingly
ReadResult deserialize(T *v) const
(1) deserialize the node's contents (val or container) to the given variable, forwarding to the user-...
Definition node.hpp:428

or, if you prefer the tree API

ryml::Tree tree = ...;
ryml::id_type node_id = ...;
if(... node is ok ...)
if(!tree.deserialize(node_id, &answer))
... // deserialization failed, react accordingly
ReadResult deserialize(id_type node, T *v) const
(1) deserialize a node's contents to a variable
Definition tree.hpp:954

Note that .deserialize() still asserts readability.



Examples

That's it! ryml provides built-in serialization/deserialization utilities for all fundamental data types, so you're good to go if that's all you are using. However, read on if you want to implement serialization with your own types.

See now the basic sample sample_serialize_basic() for a concrete working example. And if you want to use serialization with your custom user types, proceed to Serialization of user types.