YAML (YAML Ain't Markup Language) is a data language designed above all to be easy for people to read and write. Most of the configuration files you meet in modern development, from Kubernetes to GitHub Actions and Docker Compose, are written in YAML. This article walks through how it differs from JSON, the basic syntax of indentation, lists, maps, multi-line strings, and anchors, and where to use it, with example code and common pitfalls.
1. What YAML is
YAML is a data serialization language that first appeared in 2001; the current specification is YAML 1.2 (revision 1.2.2, published in 2021). The name is a recursive acronym for "YAML Ain't Markup Language": it is meant for describing configuration and data structures, not for document markup like HTML. Files use the .yaml or .yml extension.
The data structures it can express are the same as JSON's: combinations of scalars (strings, numbers, booleans, null), sequences (lists), and mappings (keys and values). As a result, almost anything written in YAML converts directly to JSON.
2. Differences from JSON
The biggest difference is who the notation is for. JSON is a minimal syntax aimed at data exchange between programs, while YAML is aimed at people editing files by hand.
| Aspect | YAML | JSON |
|---|---|---|
| Expressing structure | Indentation (spaces only) | Braces {} and brackets [] |
| Comments | Written with # | Not available |
| Quoting strings | Usually optional | Required (double quotes) |
| Multi-line strings | Natural with | and > | Escaped with \n |
| Reusing values | Anchors & / aliases * | None |
| Main uses | Configuration files (CI, IaC, and so on) | APIs and data exchange |
YAML 1.2 is designed to treat JSON almost as a subset, so most valid JSON documents can be read directly by a YAML parser. Our CSV versus JSON article also touches on choosing between formats.
3. Basic syntax - maps, lists, and nesting
Keys and values are written as key: value (always a space after the colon), and list items start with - (a hyphen followed by a space). Hierarchy is expressed with indentation, customarily two spaces. Tabs are not allowed.
# Comments are allowed (a big difference from JSON)
name: sample-app # strings usually need no quotes
version: "1.2" # quote it to keep it a string, not a number
debug: false # booleans are true / false
services: # a nested list
- name: web
port: 8080
- name: db
port: 5432
database: # a nested map
host: localhost
options:
pool: 10
Converted to JSON this becomes the following. The same structure is written in YAML without quotes or braces.
{
"name": "sample-app",
"version": "1.2",
"debug": false,
"services": [
{ "name": "web", "port": 8080 },
{ "name": "db", "port": 5432 }
],
"database": { "host": "localhost", "options": { "pool": 10 } }
}
4. Multi-line strings - | and >
Strings containing line breaks are written with block scalars. | (literal) keeps the line breaks as they are, while > (folded) converts line breaks into spaces, joining the text into one line. | suits embedded scripts, and > suits long descriptions.
script: |
echo "line one"
echo "line two" # line breaks are preserved
summary: >
This text is folded
into a single line. # line breaks become spaces
5. Anchors and aliases - reusing values
When you want to repeat the same value, mark it with &name (an anchor) and reference it with *name (an alias). Combined with <<: (the merge key), you can inherit the contents of a map and override only part of it. This is handy for reducing duplication in CI configuration.
defaults: &defaults
retries: 3
timeout: 30
production:
<<: *defaults # pull in the contents of defaults
timeout: 60 # override only timeout
staging:
<<: *defaults
JSON has no such mechanism, so converting YAML to JSON expands aliases into the actual values.
6. Where to use it, and pitfalls
YAML dominates the space of "configuration files that people read, write, and review": Kubernetes manifests, CI configuration for GitHub Actions or CircleCI, Docker Compose, Ansible playbooks, and OpenAPI definitions. Conversely, for data exchange between programs and web API responses, JSON, with its small and fast-to-parse specification, is the standard (see What Is JSON).
When writing YAML, watch out for these three points.
- Indent with spaces only. Using tabs causes a syntax error, and the same level must be indented by the same amount.
- Do not forget the space after colons and hyphens.
key:valueis wrong;key: valueis correct. - Quote ambiguous values. Under the older YAML 1.1,
no,yes,on, andoffare parsed as booleans, so the country codeNO(Norway) famously turns intofalse- the "Norway problem". YAML 1.2 fixed this, but 1.1-based parsers are still around, so writing"NO"is safest. Quotes also stop a version number like1.20from being rounded to the number1.2.
7. Try it yourself
Seeing what JSON your YAML turns into is the fastest way to understand the structure. Paste YAML into the converter below and it is converted to JSON on the spot, with syntax errors reported by line number. The reverse direction (JSON to YAML) works too.
Free Tool Try the YAML / JSON converter Convert between YAML and JSON in both directions. Syntax errors are shown with line and column numbers, and the indent width is selectable. Everything runs in your browser.8. References
This article draws on the following primary sources. See them for the full specification.
- The official specification "YAML Ain't Markup Language (YAML) version 1.2.2" (yaml.org): https://yaml.org/spec/1.2.2/
- The official js-yaml repository (a YAML 1.2 implementation for JavaScript, by nodeca): https://github.com/nodeca/js-yaml
Frequently asked questions (FAQ)
Should I use YAML or JSON?
YAML suits configuration files that people read and edit, because it supports comments and needs few symbols. JSON suits data exchange between programs, because its specification is small and unambiguous. YAML 1.2 treats JSON almost as a subset, so most valid JSON documents can be read directly as YAML.
Can I indent YAML with tabs?
No. The YAML specification allows only spaces for indentation, and using a tab character causes a syntax error. Configuring your editor to expand tabs into spaces prevents this. Two spaces is the customary width, and indentation at the same level must be aligned.
What is the "Norway problem"?
It is the nickname for a quirk of the older YAML 1.1 specification, where values such as no, yes, on, and off are interpreted as booleans, so the country code NO (Norway) unexpectedly becomes false. YAML 1.2 fixed this by limiting booleans to true and false, but YAML 1.1 parsers are still in active use, so it is safest to quote ambiguous values as "NO".