YAML Cheatsheet

Mappings and Sequences

Use this YAML reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

The two collection types

A mapping is key: value pairs. A sequence is - item lines. Nesting is by indentation, and structure comes from spaces only.

name: api
replicas: 3
labels:
  app: api
  tier: backend
ports:
  - 8080
  - 9090

parses to:

{"name": "api", "replicas": 3,
 "labels": {"app": "api", "tier": "backend"},
 "ports": [8080, 9090]}

Indentation rules

- Spaces only. A tab in the indentation is a syntax error, not a warning. a:\n\tb: 1 fails with "found character that cannot start any token". - Two spaces per level is the convention. Any consistent count works, but it must be consistent within a block. - A key with no value is null, not an empty map: a: gives {"a": null}. For an empty map or list write a: {} or a: []. - Blank lines and trailing spaces are ignored between entries.

# both of these are illegal
bad_tab:
	nested: 1        # TAB, error
bad_dedent:
    a: 1
   b: 2              # inconsistent indent, error

Sequences under a key may or may not be indented

Both forms below parse identically. The - is allowed to sit at the parent key's own column, which reads oddly but is correct YAML.

# form A, indented
ports:
  - 8080
  - 9090

# form B, flush with the key
ports:
- 8080
- 9090

Both give {"ports": [8080, 9090]}. Kubernetes manifests use form A, Ansible playbooks and docker-compose.yml often use form B. Do not "fix" one into the other in a review, and never mix them inside one block.

Mappings inside sequences

This is the alignment people get wrong. The first key sits on the same line as the -, and every sibling key aligns to that key's column, not to the dash.

containers:
  - name: api
    image: api:1.2
    ports:
      - containerPort: 8080
  - name: sidecar
    image: envoy:1.29

parses to:

{"containers": [
  {"name": "api", "image": "api:1.2",
   "ports": [{"containerPort": 8080}]},
  {"name": "sidecar", "image": "envoy:1.29"}]}

Getting image one space off puts it in the wrong dict or errors out. If your editor shows indent guides, line them up on the n of name, not the -.

Nesting patterns

ShapeYAML
map of mapsa: then indented b: 1
map of listsa: then - 1
list of maps- a: 1 then aligned b: 2
list of lists- - 1 then aligned - 2
deep mapa: b: c: each one level deeper
matrix:
  - - 1
    - 2
  - - 3

gives {"matrix": [[1, 2], [3]]}. The - - on one line is the only compact way to open a nested sequence in block style. In practice reach for flow style (matrix: [[1, 2], [3]]) instead.

Keys

Keys are scalars, so they get resolved like any other scalar. That means a key can be an int, a bool, or null, which is almost never what you want.

1: one          # integer key 1
"1": one        # string key "1"
on: yes         # PyYAML: key True, value True
a b: 1          # string key "a b", plain is fine
"a: b": 1       # quoted because of the colon-space

Duplicate keys are where parsers split. PyYAML silently keeps the last one, ruamel raises DuplicateKeyError, and yaml.v3 errors too.

port: 8080
port: 9090      # PyYAML -> {"port": 9090}, ruamel -> error

A duplicated key in a long manifest silently discards the earlier value, so run a linter (yamllint flags it as key-duplicates) rather than trusting the parser.

Complex keys

? key / : value lets a key be a whole collection. It parses structurally but most target languages cannot hold a list as a dict key.

? [Manchester, Sheffield]
: 191

PyYAML raises ConstructorError (unhashable list). You will effectively never need this, but you should recognise the ? so you do not mistake it for a typo.