2016-02-15 21:54:05 +00:00
|
|
|
============
|
|
|
|
API Overview
|
|
|
|
============
|
2016-02-15 18:46:21 +00:00
|
|
|
|
2023-11-27 22:05:05 +00:00
|
|
|
.. importdoc::
|
|
|
|
api/yaml/loading.nim, api/yaml/dumping.nim, api/yaml/annotations.nim,
|
|
|
|
api/yaml/taglib.nim, api/yaml/style.nim, api/yaml/dom.nim, api/yaml/tojson.nim,
|
|
|
|
api/yaml/parser.nim, api/yaml/presenter.nim, api/yaml/data.nim,
|
|
|
|
api/yaml/stream.nim
|
|
|
|
|
2016-02-15 21:54:05 +00:00
|
|
|
Introduction
|
|
|
|
============
|
2016-02-15 18:46:21 +00:00
|
|
|
|
|
|
|
NimYAML advocates parsing YAML input into native Nim types. Basic Nim library
|
|
|
|
types like integers, floats and strings, as well as all tuples, enums and
|
|
|
|
objects without private fields are supported out-of-the-box. Reference types are
|
|
|
|
also supported, and NimYAML is able to detect if a reference occurs more than
|
|
|
|
once and will serialize it accordingly. This means that NimYAML is able to dump
|
|
|
|
and load potentially cyclic objects.
|
|
|
|
|
|
|
|
While loading into and dumping from native Nim types is the preferred way to use
|
|
|
|
NimYAML, it also gives you complete control over each processing step, so that
|
|
|
|
you can for example only use the parser and process its event stream yourself.
|
|
|
|
The following diagram gives an overview of NimYAML's features based on the YAML
|
|
|
|
processing pipeline. The items and terminology YAML defines is shown in
|
|
|
|
*italic*, NimYAML's implementation name is shown in **bold**.
|
|
|
|
|
|
|
|
.. image:: processing.svg
|
|
|
|
|
|
|
|
Intermediate Representation
|
|
|
|
===========================
|
|
|
|
|
2023-11-27 22:05:05 +00:00
|
|
|
The base of all YAML processing with NimYAML is the `YamlStream`_. This is an
|
|
|
|
iterator over `Event`_ objects. Every proc that represents a single stage of
|
|
|
|
the loading or dumping process will either take a ``YamlStream`` as input or
|
|
|
|
return a ``YamlStream``. Procs that implement the whole process in one step
|
|
|
|
hide the ``YamlStream`` from the caller. Every proc that returns a
|
|
|
|
``YamlStream`` guarantees that this stream is well-formed according to the
|
|
|
|
YAML specification.
|
2016-02-15 18:46:21 +00:00
|
|
|
|
|
|
|
This stream-oriented API can efficiently be used to parse large amounts of data.
|
|
|
|
The drawback is that errors in the input are only discovered while processing
|
|
|
|
the ``YamlStream``. If the ``YamlStream`` encounters an exception while
|
2023-11-27 22:05:05 +00:00
|
|
|
producing the next event, it will throw a `YamlStreamError`_ which contains the
|
2016-02-15 18:46:21 +00:00
|
|
|
original exception as ``parent``. The caller should know which exceptions are
|
|
|
|
possible as parents of ``YamlStream`` because they know the source of the
|
|
|
|
``YamlStream`` they provided.
|
|
|
|
|
|
|
|
Loading YAML
|
|
|
|
============
|
|
|
|
|
2023-11-27 22:05:05 +00:00
|
|
|
If you want to load YAML character data directly into a native Nim variable,
|
|
|
|
you can use `load`_. This is the easiest and recommended way to load YAML
|
|
|
|
data. This section gives an overview about how ``load`` is implemented. It is
|
|
|
|
absolutely possible to reimplement the loading step using the low-level API.
|
2016-09-22 12:06:54 +00:00
|
|
|
|
2023-11-27 22:05:05 +00:00
|
|
|
For parsing, a `YamlParser`_ object is needed. This object stores some state
|
|
|
|
while parsing that may be useful for error reporting to the user. The `parse`_
|
2016-09-22 12:06:54 +00:00
|
|
|
proc implements the YAML processing step of the same name. All syntax errors in
|
|
|
|
the input character stream are processed by ``parse``, which will raise a
|
2023-11-27 22:05:05 +00:00
|
|
|
`YamlParserError`_ if it encounters a syntax error.
|
2016-02-15 18:46:21 +00:00
|
|
|
|
|
|
|
Transforming a ``YamlStream`` to a native YAML object is done via
|
2023-11-27 22:05:05 +00:00
|
|
|
`construct`_. It skips the **compose** step for efficiency reasons. As Nim is
|
2016-02-15 18:46:21 +00:00
|
|
|
statically typed, you have to know the target type when you write your loading
|
|
|
|
code. This is different from YAML APIs of dynamically typed languages. If you
|
|
|
|
cannot know the type of your YAML input at compile time, you have to manually
|
|
|
|
process the ``YamlStream`` to serve your needs.
|
|
|
|
|
|
|
|
Dumping YAML
|
|
|
|
============
|
|
|
|
|
2023-11-27 22:05:05 +00:00
|
|
|
Dumping is preferably done with `dump`_, which serializes a native Nim value
|
|
|
|
to a character stream. As with ``load``, this section describes how
|
|
|
|
``dump`` is implemented using the low-level API.
|
2016-09-22 12:06:54 +00:00
|
|
|
|
2023-11-27 22:05:05 +00:00
|
|
|
A Nim value is transformed into a ``YamlStream`` with `represent`_.
|
|
|
|
Depending on the `AnchorStyle`_ you specify in the `SerializationOptions`_ of
|
|
|
|
your `Dumper`_, this will transform ``ref`` variables with multiple instances
|
|
|
|
into anchored elements and aliases (for ``asTidy`` and ``asAlways``) or write
|
|
|
|
the same element into all places it occurs (for ``asNone``). Be aware that if
|
|
|
|
you use ``asNone``, the value you serialize might not round-trip.
|
2016-02-15 18:46:21 +00:00
|
|
|
|
|
|
|
Transforming a ``YamlStream`` into YAML character data is done with
|
2023-11-27 22:05:05 +00:00
|
|
|
`present`_ which is customized by your Dumper's `PresentationOptions`_. The
|
|
|
|
Dumper provides multiple presets, for example the `jsonDumper`_ dumps your
|
|
|
|
value in JSON style (which is also valid YAML since YAML is a superset of
|
|
|
|
JSON).
|
2016-02-22 20:56:30 +00:00
|
|
|
|
|
|
|
The Document Object Model
|
|
|
|
=========================
|
|
|
|
|
2022-06-05 10:27:19 +00:00
|
|
|
Unlike XML, YAML does not define an official *document object model*. However,
|
|
|
|
if you cannot or do not want to load a YAML input stream to native Nim types,
|
2023-11-27 22:05:05 +00:00
|
|
|
you can load it into the predefined type `YamlNode`_. You can also use this
|
|
|
|
type inside your native types to deserialize parts of the YAML input into it.
|
|
|
|
Likewise, you can serialize a ``YamlNode`` into YAML. You can use this to
|
|
|
|
preserve parts of YAML data you do not wish to or cannot fully deserialize.
|
|
|
|
|
|
|
|
A ``YamlNode`` preserves its given tag and the tags of any child nodes, and
|
|
|
|
also its style (which means, unless you override style with Dumper options,
|
|
|
|
the node will be serialized with the same style it had originally).
|
|
|
|
However, anchors will be resolved during loading and re-added during
|
|
|
|
serialization. It is possible for a ``YamlNode`` to occur multiple times within
|
|
|
|
source/target root object, in which case it will be serialized once and
|
|
|
|
referred to afterwards via aliases.
|
2022-06-05 10:27:19 +00:00
|
|
|
|
|
|
|
``YamlNode`` is allocated on the heap and using it will be slower and consume
|
|
|
|
more memory than deserializing into native types.
|