module YAML
Overview
The YAML module provides serialization and deserialization of YAML to/from native Crystal data structures.
Parsing with #parse
and #parse_all
YAML#parse
will return an Any
, which is a convenient wrapper around all possible YAML types,
making it easy to traverse a complex YAML structure but requires some casts from time to time,
mostly via some method invocations.
require "yaml"
data = YAML.parse <<-END
---
foo:
bar:
baz:
- qux
- fox
END
data["foo"]["bar"]["baz"][1].as_s # => "fox"
Parsing with YAML#mapping
YAML#mapping
defines how an object is mapped to YAML. Mapped data is accessible
through generated properties like Foo#bar. It is more type-safe and efficient.
Generating with YAML.build
Use YAML.build
, which uses YAML::Builder
, to generate YAML
by emitting scalars, sequences and mappings:
require "yaml"
string = YAML.build do |yaml|
yaml.mapping do
yaml.scalar "foo"
yaml.sequence do
yaml.scalar 1
yaml.scalar 2
end
end
end
string # => "---\nfoo:\n- 1\n- 2\n"
Dumping with YAML.dump
or #to_yaml
YAML.dump
generates the YAML representation for an object. An IO
can be passed and it will be written there,
otherwise it will be returned as a string. Similarly, #to_yaml
(with or without an IO
) on any object does the same.
yaml = YAML.dump({hello: "world"}) # => "---\nhello: world\n"
File.open("foo.yml", "w") { |f| YAML.dump({hello: "world"}, f) } # writes it to the file
# or:
yaml = {hello: "world"}.to_yaml # => "---\nhello: world\n"
File.open("foo.yml", "w") { |f| {hello: "world"}.to_yaml(f) } # writes it to the file
Defined in:
yaml/any.cryaml/builder.cr
yaml/mapping.cr
yaml.cr
Class Method Summary
-
.build(io : IO, &block)
Writes YAML into the given IO.
-
.build(&block)
Returns the resulting String of writing YAML to the yielded
YAML::Builder
. -
.dump(object, io : IO)
Serializes an object to YAML, writing it to io.
-
.dump(object) : String
Serializes an object to YAML, returning it as a string.
-
.parse(data : String | IO) : Any
Deserializes a YAML document.
-
.parse_all(data : String) : Array(Any)
Deserializes multiple YAML documents.
Macro Summary
-
mapping(properties, strict = false)
The
YAML.mapping
macro defines how an object is mapped to YAML. -
mapping
This is a convenience method to allow invoking
YAML.mapping
with named arguments instead of with a hash/named-tuple literal.
Class Method Detail
Writes YAML into the given IO. A YAML::Builder
is yielded to the block.
Returns the resulting String of writing YAML to the yielded YAML::Builder
.
require "yaml"
string = YAML.build do |yaml|
yaml.mapping do
yaml.scalar "foo"
yaml.sequence do
yaml.scalar 1
yaml.scalar 2
end
end
end
string # => "---\nfoo:\n- 1\n- 2\n"
Serializes an object to YAML, returning it as a string.
Deserializes a YAML document.
# ./foo.yml
data:
string: "foobar"
array:
- John
- Sarah
hash: {key: value}
paragraph: |
foo
bar
require "yaml"
YAML.parse(File.read("./foo.yml"))
# => {
# => "data" => {
# => "string" => "foobar",
# => "array" => ["John", "Sarah"],
# => "hash" => {"key" => "value"},
# => "paragraph" => "foo\nbar\n"
# => }
Deserializes multiple YAML documents.
# ./foo.yml
foo: bar
---
hello: world
require "yaml"
YAML.parse_all(File.read("./foo.yml"))
# => [{"foo" => "bar"}, {"hello" => "world"}]
Macro Detail
The YAML.mapping
macro defines how an object is mapped to YAML.
It takes named arguments, a named tuple literal or a hash literal as argument,
in which attributes and types are defined.
Once defined, Object#from_yaml
populates properties of the class from the
YAML document.
require "yaml"
class Employee
YAML.mapping(
title: String,
name: String,
)
end
employee = Employee.from_yaml("title: Manager\nname: John")
employee.title # => "Manager"
employee.name # => "John"
employee.name = "Jenny"
employee.name # => "Jenny"
Attributes not mapped with YAML.mapping
are not defined as properties.
Also, missing attributes raise a ParseException
.
employee = Employee.from_yaml("title: Manager\nname: John\nage: 30")
employee.age # undefined method 'age'. (compile error)
Employee.from_yaml("title: Manager") # raises YAML::ParseException
You can also define attributes for each property.
class Employer
YAML.mapping(
title: String,
name: {
type: String,
nilable: true,
key: "firstname",
},
)
end
Available attributes:
- type (required) defines its type. In the example above, title: String is a shortcut to title: {type: String}.
- nilable defines if a property can be a
Nil
. PassingT?
as a type has the same effect. - default: value to use if the property is missing in the YAML document, or if it's
null
andnilable
was not set totrue
. If the default value creates a new instance of an object (for example[1, 2, 3]
orSomeObject.new
), a different instance will be used each time a YAML document is parsed. - key defines which key to read from a YAML document. It defaults to the name of the property.
- converter takes an alternate type for parsing. It requires a
#from_yaml
method in that class, and returns an instance of the given type. Examples of converters areTime::Format
andTime::EpochConverter
forTime
. - setter: if
true
, will generate a setter for the variable,true
by default - getter: if
true
, will generate a getter for the variable,true
by default
This macro by default defines getters and setters for each variable (this can be overrided with setter and getter). The mapping doesn't define a constructor accepting these variables as arguments, but you can provide an overload.
The macro basically defines a constructor accepting a YAML::PullParser
that reads from
it and initializes this type's instance variables.
This macro also declares instance variables of the types given in the mapping.
This is a convenience method to allow invoking YAML.mapping
with named arguments instead of with a hash/named-tuple literal.