If you’re working with configuration files, data serialization, or DevOps tools, you might have encountered YAML (YAML Ain’t Markup Language). YAML is popular for its simplicity and readability, making it an excellent choice for defining configuration files. In this blog post, we’ll introduce you to YAML, explain its syntax, and provide examples to help you get started.

What is YAML?

YAML (pronounced /ˈjæməl/) is a human-readable data serialization format that is often used for configuration files and data exchange between programming languages. It’s designed to be easily readable and writable by humans, which is why it’s favored in many domains, including DevOps (e.g., Ansible, Kubernetes, Docker Compose).

Its basic syntax rules are:

  1. Case-sensitive.
  2. Uses indentation to represent hierarchical relationships.
  3. Tabs are not allowed for indentation; only spaces are permitted.
  4. The number of spaces in indentation doesn’t matter, as long as elements at the same level are aligned.
  5. ‘#’ indicates a comment; everything from this character to the end of the line is ignored by the parser.

YAML supports three types of data structures:

  1. Objects: Collections of key-value pairs, also known as mappings, hashes, or dictionaries.
  2. Arrays: Ordered lists of values, also called sequences or lists.
  3. Scalars: Single, indivisible values.

Let’s explore each of these data structures in more detail.

Objects

In YAML, key-value pairs are represented using a colon(:).
For example:

1
2
name: Johnson Lin
age: 28
  • The basic building block of YAML is a key-value pair, where a key is followed by a colon : and a value.
  • Indentation (usually 2 spaces) defines nested structures.

This translates to JavaScript as:

1
{ name: 'Johnson Lin', age: 28 }

YAML also supports another format where all key-value pairs are written as an inline object:

1
person: { name: Johnson Lin, age: 28 }

In JavaScript, this becomes:

1
{ person: { name: 'Johnson Lin', age: 28 } }

Arrays

A list of items starting with hyphens forms an array:

1
2
3
- Apple
- Banana
- Cherry
  • YAML lists are indicated by a hyphen -, with each list item on a new line and indented.

In JavaScript, this translates to:

1
[ 'Apple', 'Banana', 'Cherry' ]

If an array is a sub-member of a data structure, it can be indented below the item:

1
2
3
4
- 
- Apple
- Banana
- Cherry

This becomes in JavaScript:

1
[ [ 'Apple', 'Banana', 'Cherry' ] ]

Arrays can also be represented inline:

1
fruits: [Apple, Banana, Cherry]

In JavaScript:

1
{ fruits: [ 'Apple', 'Banana', 'Cherry' ] }

Composite Structures

Objects and arrays can be combined to form complex structures:

1
2
3
4
5
6
7
8
application:
name: MyApp
version: 1.0.0

services:
- UserService
- OrderService
- ProductService

In JavaScript, this looks like:

1
2
3
4
5
6
7
{
services: [ 'UserService', 'OrderService', 'ProductService' ],
application: {
name: 'MyApp',
version: '1.0.0'
}
}

Scalars

Scalars are the most basic, indivisible values. In JavaScript, these include:

  • Strings
  • Booleans
  • Integers
  • Floats
  • Null
  • Dates

Scalars are represented directly as literals:
For example:

1
number: 20.32

In JavaScript:

1
{ number: 20.32 }

Booleans are represented as true or false:

1
isNumber: true

In JavaScript:

1
{ isNumber: true }

null is represented as ~:

1
image: ~

In JavaScript:

1
{ image: null }

Dates use the ISO 8601 format:

1
iso8601: 2024-08-27T02:29:19.10-08:00

In JavaScript:

1
{ iso8601: new Date('2024-08-27T02:29:19.10-08:00') }

Dates in ISO 8601 format can also be represented by year, month, and day:

1
date: 2024-08-27

In JavaScript:

1
{ date: new Date('2024-08-27') }

YAML allows type coercion with double exclamation marks:

1
2
n: !!str 7890
f: !!str true

In JavaScript:

1
{ n: '7890', f: 'true' }

Strings

Strings do not require quotes unless they contain special characters or whitespace.
Example:

1
str: This is a string

In JavaScript:

1
{ str: 'This is a string' }

If a string contains spaces or special characters, it needs to be enclosed in quotes.
Example:

1
str: 'Johnson: Hello, World!'

In JavaScript:

1
{ str: 'Johnson: Hello, World!' }

Both single and double quotes can be used, but double quotes do not escape special characters.
Examples:

1
2
s1: 'Content\nString'
s2: "Content\nString"

In JavaScript:

1
{ s1: 'Content\\nString', s2: 'Content\nString' }

To escape single quotes within single-quoted strings, use two single quotes.
Example:

1
str: 'It''s cloudy today.'

In JavaScript:

1
{ str: 'It\'s cloudy today.' }

Strings can span multiple lines. From the second line, there must be a single space indentation. Newlines are replaced with spaces.
Example:

1
2
3
str: This is a
multi-line
string

In JavaScript:

1
{ str: 'This is a multi-line string' }

Multi-line strings can preserve newlines using | or fold newlines using >.
Example:

1
2
3
4
5
6
this: |
Foo
Bar
that: >
Foo
Bar

In JavaScript:

1
{ this: 'Foo\nBar\n', that: 'Foo Bar\n' }

+ keeps trailing newlines, while - removes them.
Examples:

1
2
3
4
5
6
7
8
s1: |
Foo

s2: |+
Foo

s3: |-
Foo

In JavaScript:

1
{ s1: 'Foo\n', s2: 'Foo\n\n\n', s3: 'Foo' }

HTML tags can be included in strings.
Example:

1
2
3
4
5
6
message: |

<p style="color: red">
Paragraph
</p>

In JavaScript:

1
{ message: '\n<p style="color: red">\n  Paragraph\n</p>\n' }

Comments

Comments in YAML begin with a hash # and can be placed anywhere in the file.
Example:

1
2
# This is a comment
name: Johnson Lin # Inline comment

References

Anchor (&) and alias (*) can be used for references.
Example:

1
2
3
4
5
6
7
8
9
10
11
defaults: &defaults
adapter: postgres
host: localhost

development:
database: myapp_development
<<: *defaults

test:
database: myapp_test
<<: *defaults

Equivalent JavaScript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
defaults: {
adapter: 'postgres',
host: 'localhost'
}

development: {
database: 'myapp_development',
adapter: 'postgres',
host: 'localhost'
}

test: {
database: 'myapp_test',
adapter: 'postgres',
host: 'localhost'
}

& creates an anchor (defaults), << merges into the current data, and * references the anchor.
Another example:

1
2
3
4
5
- &showell Steve
- Clark
- Brian
- Oren
- *showell

In JavaScript:

1
[ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ]

Functions and Regular Expressions

The JS-YAML library allows functions and regular expressions to be converted to strings.
Example example.yml:

1
2
fn: function () { return 1 }
reg: /test/

Parsing code:

1
2
3
4
5
6
7
8
9
var yaml = require('js-yaml');
var fs = require('fs');

try {
var doc = yaml.load(fs.readFileSync('./example.yml', 'utf8'));
console.log(doc);
} catch (e) {
console.log(e);
}

Converting JavaScript objects back to YAML:

1
2
3
4
5
6
7
8
9
10
11
12
13
var yaml = require('js-yaml');
var fs = require('fs');

var obj = {
fn: function () { return 1 },
reg: /test/
};

try {
fs.writeFileSync('./example.yml', yaml.dump(obj), 'utf8');
} catch (e) {
console.log(e);
}

YAML vs. JSON

YAML and JSON are both data serialization formats, but YAML is often considered more human-friendly due to its clean syntax. For example, YAML doesn’t require curly braces {}, square brackets [], or commas ,. This makes YAML files easier to write and maintain, especially when working with complex configurations.

YAML Example

Here’s a more detailed example that showcases different YAML features:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# YAML configuration file example
application:
name: MyApp
version: 1.0.0

environment: production

database:
host: localhost
port: 5432
username: admin
password: secret

services:
- name: web
image: nginx:latest
ports:
- 80:80
- name: db
image: postgres:latest
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret

In this example:

  • application: is a dictionary containing the app’s name and version.
  • environment: is a simple key-value pair.
  • database: is another dictionary defining database configuration.
  • services: is a list of dictionaries, each describing a service with its configuration.

Common YAML Syntax Errors

  • Indentation Errors: YAML relies on consistent indentation. Make sure you use spaces (not tabs) and maintain the same number of spaces for each level.
  • Colons and Spaces: Ensure there is a space after the colon in key-value pairs (e.g., key: value).
  • Special Characters: If a value contains special characters (e.g., : or #), wrap it in quotes.

Conclusion

YAML is a powerful, yet simple, data serialization format that’s widely used for configuration files and data exchange. Its clear and concise syntax makes it easy to write and maintain, especially for complex structures. As you start working with YAML, remember to focus on proper indentation and structure to avoid common syntax errors.

Pro Tip: Use online tools like YAML Lint to validate your YAML files and catch errors early.

Now that you’ve got the basics down, you’re ready to start writing YAML files for your projects. Happy configuring!

Reference Links:
YAML 1.2 Specification
YAML on Wikipedia
YAML for Ruby