Groovy has an optional groovy-yaml module which provides support for converting between Groovy objects and YAML. The classes dedicated to
YAML serialization and parsing are found in the groovy.yaml package.
1. YamlSlurper
YamlSlurper is a class that parses YAML text or reader content into Groovy data structures (objects) such as maps, lists and
primitive types like Integer, Double, Boolean and String.
The class comes with a bunch of overloaded parse methods plus some special methods such as parseText
and others. For the next example we will use the parseText method. It parses a YAML String and recursively converts it to a
list or map of objects. The other parse* methods are similar in that they return a YAML String but for different parameter
types.
def ys = new YamlSlurper()
def yaml = ys.parseText '''
language: groovy
sudo: required
dist: trusty
matrix:
include:
- jdk: openjdk10
- jdk: oraclejdk9
- jdk: oraclejdk8
before_script:
- |
unset _JAVA_OPTIONS
'''
assert 'groovy' == yaml.language
assert 'required' == yaml.sudo
assert 'trusty' == yaml.dist
assert ['openjdk10', 'oraclejdk9', 'oraclejdk8'] == yaml.matrix.include.jdk
assert ['unset _JAVA_OPTIONS'] == yaml.before_script*.trim()
Notice the result is a plain map and can be handled like a normal Groovy object instance. YamlSlurper parses the
given YAML as defined by the YAML Ain’t Markup Language (YAML™).
As YamlSlurper is returning pure Groovy object instances without any special YAML classes in the back, its usage
is transparent. In fact, YamlSlurper results conform to GPath expressions. GPath is a powerful expression language
that is supported by multiple slurpers for different data formats (XmlSlurper for XML being one example).
| For more details please have a look at the section on GPath expressions. |
The following table gives an overview of the YAML types and the corresponding Groovy data types:
| YAML | Groovy |
|---|---|
string |
|
number |
|
object |
|
array |
|
true |
|
false |
|
null |
|
date/time |
|
Whenever a value in YAML is null, YamlSlurper supplements it with the Groovy null value. This is in contrast to other
YAML parsers that represent a null value with a library-provided singleton object.
|
|
For the untyped |
1.1. Typed parsing
YamlSlurper can parse YAML directly into typed objects using Jackson databinding.
Standard Jackson annotations such as @JsonProperty and @JsonFormat are supported
for property mapping and type conversion:
static class ServerConfig {
String host
int port
}
def config = new YamlSlurper().parseTextAs(ServerConfig, '''\
host: localhost
port: 8080
''')
assert config.host == 'localhost'
assert config.port == 8080
For simple cases, Groovy’s as coercion also works with the untyped result:
def config = new YamlSlurper().parseText(yaml) as ServerConfig.
The parseTextAs method uses Jackson databinding, which supports richer annotation-driven
mapping via @JsonProperty, @JsonFormat, etc.
|
1.2. Typed date and time values
When a target type declares java.time.* fields, the typed parseAs/parseTextAs
API and YamlBuilder.toYaml round-trip YAML temporal values with full fidelity,
including the original zone offset for OffsetDateTime:
static class Event {
java.time.OffsetDateTime created
java.time.LocalDate effective
java.time.LocalTime windowStart
java.time.LocalDateTime updated
String name
}
def original = new Event(
created: java.time.OffsetDateTime.parse('1979-05-27T07:32:00-08:00'),
effective: java.time.LocalDate.of(1979, 5, 27),
windowStart: java.time.LocalTime.of(7, 32, 0),
updated: java.time.LocalDateTime.of(1979, 5, 27, 7, 32, 0),
name: 'demo')
def yaml = YamlBuilder.toYaml(original)
def parsed = new YamlSlurper().parseTextAs(Event, yaml)
assert parsed.created == original.created // OffsetDateTime, non-UTC offset preserved
assert parsed.effective == original.effective // LocalDate
assert parsed.windowStart == original.windowStart // LocalTime
assert parsed.updated == original.updated // LocalDateTime
assert parsed.name == original.name
1.3. Builders
Another way to create YAML from Groovy is to use YamlBuilder. The builder provide a
DSL which allows to formulate an object graph which is then converted to YAML.
def builder = new YamlBuilder()
builder.records {
car {
name 'HSV Maloo'
make 'Holden'
year 2006
country 'Australia'
homepage new URL('http://example.org')
record {
type 'speed'
description 'production pickup truck with speed of 271kph'
}
}
}
assert builder.toString() == '''---
records:
car:
name: "HSV Maloo"
make: "Holden"
year: 2006
country: "Australia"
homepage: "http://example.org"
record:
type: "speed"
description: "production pickup truck with speed of 271kph"
'''
1.4. Typed writing
YamlBuilder.toYaml(object) serializes a typed object directly to YAML using Jackson databinding:
static class ServerConfig {
String host
int port
}
@Test
void testToYaml() {
def config = new ServerConfig(host: 'localhost', port: 8080)
def yaml = YamlBuilder.toYaml(config)
assert yaml.contains('host:')
assert yaml.contains('localhost')
assert yaml.contains('port:')
assert yaml.contains('8080')
}