Plain unquoted string β most common
name: John Doe
Single-quoted: no variable or escape processing
path: '/usr/bin/node'
Double-quoted: supports escape sequences (\n, \t, etc.)
message: "Hello\nWorld"
Whole number (base 10)
port: 8080
Floating point number
threshold: 0.95
Boolean value β use only true/false (YAML 1.2)
debug: false
Null / absence of value
response: null
ISO 8601 date format
created: 2024-01-15T10:30:00Z
Single-line comment. No multi-line comment syntax.
# This is a comment key: value # inline comment
Force value to be treated as a specific type
port: !!str 8080 # string '8080' not int
Key-value pairs β indented block style
app: name: myapp port: 3000
Inline map β equivalent to block style
env: {NODE_ENV: prod, PORT: 8080}List of items β block style with dash+space
fruits: - apple - banana - cherry
Inline list β equivalent to block style
ports: [80, 443, 8080]
List where each item is a map
users:
- name: Alice
role: admin
- name: Bob
role: userArbitrarily deep nesting
database:
primary:
host: db1.example.com
port: 5432Merge the keys of a referenced mapping into current map
defaults: &defaults color: blue button: <<: *defaults text: Submit
Preserves newlines exactly as written
script: | #!/bin/bash echo "hello" exit 0
Newlines folded into spaces (great for long descriptions)
description: > This is a very long description that will be joined into one line.
Literal block, strip all trailing newlines
prompt: |- Enter value:
Literal block, keep all trailing newlines
template: |+ line1
Folded block, strip trailing newlines
message: >- This folds into one line no trailing newline
Assigns an anchor (label) to the current node
base: &base image: node:18 restart: always
References (copies) an anchored node
service1: <<: *base name: api service2: <<: *base name: worker
Anchor a scalar value to reuse it
read_timeout: &rto 30 write_timeout: *rto connect_timeout: *rto
Anchor a list
primary_colors: &colors - red - blue text_colors: *colors
Explicitly declare YAML version (optional, rarely needed)
%YAML 1.2 --- name: myapp
Marks the start of a YAML document. Required if using directives.
--- kind: Deployment --- kind: Service
Marks the end of a YAML document. Optional but useful.
--- debug: true ...
Multiple YAML docs in one file (stream)
Used in Kubernetes multi-resource files
Base64-encoded binary data
icon: !!binary | iVBORw0KGgo=
Indentation MUST use spaces only β never tabs
# WRONG: parent: \tchild: value # RIGHT: parent: child: value
Values containing ': ' (colon+space) must be quoted
# WRONG: url: http://example.com # RIGHT: url: "http://example.com"
1.0 parses as float! Quote or tag it to keep as string
version: '1.0' # string version: 1.0 # float
YAML 1.1 parses yes/no/on/off as booleans β quote to use strings
# YAML 1.1 (PyYAML): on: true # 'on' is boolean true! # Safe: always quote on: 'on'
Trailing spaces in keys are included in the key string
"key " (with space) != "key" β trim carefully
Duplicate keys β behavior is parser-specific (usually last wins). Treat as error.
Use a YAML linter to detect duplicate keys
| Feature | YAML | JSON |
|---|---|---|
| Comments | Yes: # comment | Not supported |
| Quotes required | Optional for strings | Required for strings |
| Anchors/aliases | Yes: &anchor / *alias | Not supported |
| Multi-line strings | Yes: | and > blocks | Escaped \n only |
| Tabs for indentation | Spaces only | Either |
| Is superset of JSON | All JSON is valid YAML | - |
| Human readability | Very high | Medium |
| Parser availability | High | Very high |
Critical: Many YAML parsers still use YAML 1.1 by default (Python's PyYAML, Ruby's Psych in some versions).
YAML has two multiline styles:
Literal block (|) β preserves line breaks:
description: |
This is line one.
This is line two.
This is line four (after blank line).
Folded block (>) β joins lines with spaces:
description: >
This is a long paragraph
that will be folded into
a single line.
Add - to strip trailing newlines (|-, >-) or + to keep them (|+, >+).
A single YAML file can contain multiple documents separated by ---:
---
# Document 1: Config
apiVersion: v1
kind: ConfigMap
---
# Document 2: Service
apiVersion: v1
kind: Service
This is commonly used in Kubernetes manifests.
Two spaces is the most common convention, used by Kubernetes, Docker Compose, GitHub Actions, and most DevOps tools. Some projects use four spaces. The key rule is consistency within a file β never mix indentation levels.
Yes, YAML supports single-line comments with #. There is no multi-line comment syntax. Comments are stripped during parsing and not available in the loaded data structure.
YAML is a superset of JSON β any valid JSON is valid YAML. YAML is designed to be more human-readable with less punctuation. It supports comments (# comment), anchors/aliases for deduplication, multi-line strings, and is whitespace-sensitive. JSON is better for machine-to-machine communication and data interchange; YAML is preferred for configuration files.
In YAML 1.1 (used by many parsers including PyYAML), 'on', 'off', 'yes', 'no' are valid boolean values. YAML 1.2 removed this behavior β only 'true' and 'false' are booleans. This is a common pitfall in CI/CD configs (e.g., 'on' in GitHub Actions is a workflow trigger keyword, not a YAML boolean). Quote these values or use true/false explicitly.
Use the literal block scalar (|) to preserve newlines: each line in the block becomes a literal newline in the string. Use the folded block scalar (>) to fold newlines into spaces (great for long descriptions). Both support the - and + chomping indicators to control trailing newlines: |- strips trailing newlines, |+ keeps all trailing newlines.
YAML uses spaces for indentation β never tabs. All sibling keys must be at the same indentation level. A common cause is mixing tabs and spaces, or inconsistent indentation within sequences. Lists under a key must be indented by at least 1 space more than the parent key. Use a YAML linter or validator to quickly find indentation issues.