Wiki
Clone wikisnakeyaml-engine / Documentation
SnakeYAML Engine Documentation
This documentation is very brief and incomplete. Feel free to fix or improve it.
Installation
If you use Maven just add a dependency as described here.
Tutorial
Loading YAML
The Builder pattern is used to create immutable instance of org.snakeyaml.engine.v2.api.LoadSettings
LoadSettings settings = LoadSettings.builder().setLabel("Custom user configuration").build();
Create the org.snakeyaml.engine.v2.api.Load
instance:
Load load = new Load(settings);
The org.snakeyaml.engine.v2.api.Load
instance can load 3 types of sources:
- InputStream
- Reader
- String
The InputStream does not contain the encoding information and to detect the encoding the BOM (byte order mark) sequence at the beginning of the stream can be used. If no BOM is present, the UTF-8 encoding is assumed.
The Reader and String define the encoding and the BOM must not be present (it will be interpreted as data).
These methods convert a YAML document to a Java object:
- loadFromInputStream
- loadFromReader
- loadFromString
Load load = new Load(settings); String document = "\n- Hesperiidae\n- Papilionidae\n- Apatelodidae\n- Epiplemidae"; List<String> list = (List<String>) yaml.loadFromString(document); System.out.println(list); ['Hesperiidae', 'Papilionidae', 'Apatelodidae', 'Epiplemidae']
Implicit types
When a tag for a scalar node is not explicitly defined, SnakeYAML Engine tries to detect the type applying regular expressions to the content of the scalar node.
1.0 -> Double 42 -> Integer null -> null false -> boolean
The Core Schema requires to write a custom implementation
of the ScalarResolver
(it might be added in the next versions).
Dumping YAML
The Builder pattern is used to create immutable instance of org.snakeyaml.engine.v2.api.DumpSettings
DumpSettings settings = DumpSettings.builder().setDefaultScalarStyle(ScalarStyle.DOUBLE_QUOTED).build();
Create the org.snakeyaml.engine.v2.api.Dump
instance:
Dump dump = new Dump(settings);
The method Dump.dumpToString()
takes an instance and returns its YAML document.
The method Dump.dumpAllToString()
takes an java.util.Iterator
and returns a YAML stream with all the documents
included. The documents are separated as defined in the DumpSettings
.
To support output to streams Dump
has dump()
and dumpAll()
. They take an instance of StreamDataWriter
as a parameter.
The interface is identical to java.io.Writer
but without throwing IOExceptions. It means that the user has to create
the implementation of the interface and take care of catching the I/O exceptions.
Working examples can be found in the tests
Dumping a custom YAML document
TODO
Constructors, representers, resolvers
TODO
Enum
TODO
Threading
The implementation is not thread-safe. Different threads may not call the same instance.
Threads must have separate Load
or Dump
instances.
Low Level API
It is possible to parse or compose the incoming stream of characters. Examples can be found here for parsing or here for composing.
Tags
Explicit tags can be local (begin with single exclamation mark '!car') and global (begin with 2 exclamation marks '!!com.Car').
Global tags work well within a single programming language, because they can be parsed without extra configuration.
Local tags require additional context. Since every parser must provide more information at runtime to create instances,
local tags help a YAML document to be exchanged with other languages (every parser is free to define what to do with !car
)
Implicit tags are assigned to every scalar and they are determined from the regular expressions. It is possible to add custom implicit tags. When a scalar is created the following order is used:
-
explicit tag - when it is present.
-
implicit tag - when the runtime class of the instance is unknown
It means that the implicit tag is ignored as soon as any other information about a scalar is available.
YAML syntax
A good introduction to the YAML syntax is Chapter 2 of the YAML specification.
Here we present most common YAML constructs together with the corresponding Java objects.
Documents
YAML stream is a collection of zero or more documents. An empty stream contains no documents.
Documents are separated with ---
. Documents may optionally end with ...
.
A single document may or may not be marked with ---
.
Example of an implicit document:
- Multimedia - Internet - Education
Example of an explicit document:
--- - Afterstep - CTWM - Oroborus ...
Example of several documents in the same stream:
--- - Ada - APL - ASP - Assembly - Awk --- - Basic --- - C - C# # Note that comments are denoted with ' #' (space and #). - C++ - Cold Fusion
Block sequences
In the block context, sequence entries are denoted by -
(dash and space):
# YAML - The Dagger 'Narthanc' - The Dagger 'Nimthanc' - The Dagger 'Dethanc'
# Java ["The Dagger 'Narthanc'", "The Dagger 'Nimthanc'", "The Dagger 'Dethanc'"]
Block sequences can be nested:
# YAML - - HTML - LaTeX - SGML - VRML - XML - YAML - - BSD - GNU Hurd - Linux
# Java [['HTML', 'LaTeX', 'SGML', 'VRML', 'XML', 'YAML'], ['BSD', 'GNU Hurd', 'Linux']]
It's not necessary to start a nested sequence with a new line:
# YAML - 1.1 - - 2.1 - 2.2 - - - 3.1 - 3.2 - 3.3
# Java [1.1, [2.1, 2.2], [[3.1, 3.2, 3.3]]]
A block sequence may be nested to a block mapping. Note that in this case it is not necessary to indent the sequence.
# YAML left hand: - Ring of Teleportation - Ring of Speed right hand: - Ring of Resist Fire - Ring of Resist Cold - Ring of Resist Poison
# Java {'right hand': ['Ring of Resist Fire', 'Ring of Resist Cold', 'Ring of Resist Poison'], 'left hand': ['Ring of Teleportation', 'Ring of Speed']}
Block mappings
In the block context, keys and values of mappings are separated by :
(colon and space):
# YAML base armor class: 0 base damage: [4,4] plus to-hit: 12 plus to-dam: 16 plus to-ac: 0
# Java {'plus to-hit': 12, 'base damage': [4, 4], 'base armor class': 0, 'plus to-ac': 0, 'plus to-dam': 16}
Complex keys are denoted with ?
(question mark and space):
# YAML ? !!python/tuple [0,0] : The Hero ? !!python/tuple [0,1] : Treasure ? !!python/tuple [1,0] : Treasure ? !!python/tuple [1,1] : The Dragon
# Java {(0, 1): 'Treasure', (1, 0): 'Treasure', (0, 0): 'The Hero', (1, 1): 'The Dragon'}
Block mapping can be nested:
# YAML hero: hp: 34 sp: 8 level: 4 orc: hp: 12 sp: 0 level: 2
# Java {'hero': {'hp': 34, 'sp': 8, 'level': 4}, 'orc': {'hp': 12, 'sp': 0, 'level': 2}}
A block mapping may be nested in a block sequence:
# YAML - name: PyYAML status: 4 license: MIT language: Python - name: PySyck status: 5 license: BSD language: Python
# Java [{'status': 4, 'language': 'Python', 'name': 'PyYAML', 'license': 'MIT'}, {'status': 5, 'license': 'BSD', 'name': 'PySyck', 'language': 'Python'}]
Flow collections
The syntax of flow collections in YAML is very close to the syntax of list and dictionary constructors in Python:
# YAML { str: [15, 17], con: [16, 16], dex: [17, 18], wis: [16, 16], int: [10, 13], chr: [5, 8] }
# Java {'dex': [17, 18], 'int': [10, 13], 'chr': [5, 8], 'wis': [16, 16], 'str': [15, 17], 'con': [16, 16]}
Scalars
There are 5 styles of scalars in YAML: plain, single-quoted, double-quoted, literal, and folded:
# YAML plain: Scroll of Remove Curse single-quoted: 'EASY_KNOW' double-quoted: "?" literal: | # Borrowed from http://www.kersbergen.com/flump/religion.html by hjw ___ __ /.-.\ / )_____________\\ Y /_ /=== == === === =\ _\_ ( /)=== == === === == Y \ `-------------------( o ) \___/ folded: > It removes all ordinary curses from all equipped items. Heavy or permanent curses are unaffected.
# Java {'plain': 'Scroll of Remove Curse', 'literal': 'by hjw ___\n' ' __ /.-.\\\n' ' / )_____________\\\\ Y\n' ' /_ /=== == === === =\\ _\\_\n' '( /)=== == === === == Y \\\n' ' `-------------------( o )\n' ' \\___/\n', 'single-quoted': 'EASY_KNOW', 'double-quoted': '?', 'folded': 'It removes all ordinary curses from all equipped items. Heavy or permanent curses are unaffected.\n'}
Each style has its own quirks. A plain scalar does not use indicators to denote its start and end, therefore it's the most restricted style. Its natural applications are names of attributes and parameters.
Using single-quoted scalars, you may express any value that does not contain special characters.
No escaping occurs for single quoted scalars except that duplicate quotes ''
are replaced
with a single quote '
.
Double-quoted is the most powerful style and the only style that can express any scalar value.
Double-quoted scalars allow escaping. Using escaping sequences \x**
and \u****
,
you may express any ASCII or Unicode character.
There are two kind of block scalar styles: literal and folded. The literal style is the most suitable style for large block of text such as source code. The folded style is similar to the literal style, but two consequent non-empty lines are joined to a single line separated by a space character.
Aliases
Using YAML you may represent objects of arbitrary graph-like structures. If you want to refer to the same object from different parts of a document, you need to use anchors and aliases.
Anchors are denoted by the &
indicator while aliases are denoted by *
. For instance,
the document
left hand: &A name: The Bastard Sword of Eowyn weight: 30 right hand: *A
SnakeYAML now fully supports recursive objects. For instance, the document
&A [ *A ]
Tags
Tags are used to denote the type of a YAML node. Standard YAML tags are defined at http://yaml.org/type/index.html.
Tags may be implicit:
boolean: true integer: 3 float: 3.14
#!python {'boolean': True, 'integer': 3, 'float': 3.14}
or explicit:
boolean: !!bool "true" integer: !!int "3" float: !!float "3.14"
#!python {'boolean': True, 'integer': 3, 'float': 3.14}
Plain scalars without explicitly defined tag are subject to implicit tag resolution. The scalar value is checked against a set of regular expressions and if one of them matches, the corresponding tag is assigned to the scalar. SnakeYAML allows an application to add custom implicit tag resolvers.
YAML tags and Java types
The following table describes how nodes with different tags are converted to Java objects.
YAML tag | Java type |
---|---|
Standard YAML tags | |
!!null |
null |
!!bool |
Boolean |
!!int |
Integer, Long, BigInteger |
!!float |
Double |
!!binary |
byte[] , String |
!!omap , !!pairs |
List of Object[] |
!!set |
Set |
!!str |
String |
!!seq |
List |
!!map |
Map |
Collections
Default implementations of collections are:
-
List:
ArrayList
-
Map:
LinkedHashMap
(the order is implicitly defined)
It is possible to define other default implementations. It must be specified as a function from init size to the collection implementation. An example can be found here for List and for Map
ENV Variable substitution
SnakeYAML Engine provides a way to make ENV Variable substitution similar to how it works for Docker compose
Only ${VARIABLE}
syntax is supported.
it is possible to provide inline default values using typical shell syntax (exactly as for docker-compose):
${VARIABLE:-default}
evaluates todefault
ifVARIABLE
is unset or empty in the environment.${VARIABLE-default}
evaluates todefault
only ifVARIABLE
is unset in the environment.${VARIABLE:?err}
exits with an error message containingerr
ifVARIABLE
is unset or empty in the environment.${VARIABLE?err}
exits with an error message containingerr
ifVARIABLE
is unset in the environment.
If variable is not set, the empty value is used. Except when it is explicitly instructed to fail.
Since SnakeYAML is no template engine, it does not substitute parts of scalar, only the whole scalar. For instance this stays as it is because template is just a part of the scalar:
environment: - DEBUG=${DEBUG} - "DIR=${DATA_DIR}"
environment: DEBUG: ${DEBUG} DIR: ${DATA_DIR}
An example can be found it tests.
Merge
YAML has a "merge" specification: http://yaml.org/type/merge.html
This tag is no more supported in YAML 1.2 and its implementation has been removed from SnakeYAML Engine.
Deviations from the specification
to be found...
Updated