The two-line answer
- Wire format between programs? JSON. It's faster to parse, has no version drift, and every language ships a parser.
- Config file humans edit? YAML (or TOML). Comments, multiline strings, and less syntactic noise.
Side by side
The same data in both formats:
# YAML
name: my-app
version: 1.0.0
ports:
- 80
- 443
config:
debug: false
timeout: 30
# Retry logic was added in v1.0
retries: 3 // JSON
{
"name": "my-app",
"version": "1.0.0",
"ports": [80, 443],
"config": {
"debug": false,
"timeout": 30,
"retries": 3
}
}
Same data tree. YAML drops the braces, brackets, quotes, and
commas in exchange for caring about indentation. The
# comment in YAML has no JSON equivalent.
Quick syntax differences
| Feature | YAML | JSON |
|---|---|---|
| Comments | # inline | Not allowed |
| Trailing commas | N/A | Not allowed |
| Single quotes | Allowed | Not allowed |
| Unquoted keys | Default | Not allowed |
| Unquoted strings | Allowed (with caveats) | Not allowed |
| Multiline strings | Native (|, >) | Use \n in a single-line string |
| References / aliases | & and * | None |
| Multiple documents per file | Yes (--- separator) | No |
| Tabs allowed for indent | No (most parsers reject) | N/A — no indent |
| Spec size | ~80 pages | ~16 pages |
Where YAML wins
Configuration files
Kubernetes manifests, GitHub Actions, Ansible playbooks, Docker Compose, CircleCI configs — all use YAML, all for the same reason: humans read and edit these by hand. JSON's required quotes and commas make it painful for files larger than ~50 lines.
Multiline content
Embedding a SQL query, a shell script, or a long template in JSON
means escaping every newline as \n in a single string.
YAML's block scalars (| and >) keep
the content readable.
Multiline strings have their own
guide.
Repetition reduction
YAML's anchors (&name) and aliases
(*name) let you define a chunk of config once and
reuse it. JSON has no equivalent — you copy-paste or use a
templating system.
Anchors and aliases guide.
Where JSON wins
Speed
JSON parsers are 5-50× faster than YAML parsers. For a config file loaded once at startup, the difference is invisible. For a wire format processing thousands of messages per second, JSON's lead is decisive.
Predictability
JSON has one canonical interpretation. YAML has at least two
common ones (1.1 and 1.2) that disagree about whether
off means false, whether 010 is octal,
and whether unquoted NO is a country code or a
boolean. The YAML parser version matters; JSON parsers don't.
Tooling and security
Every WAF, every API gateway, every framework expects JSON in HTTP
bodies. YAML parsers have a long history of CVEs (PyYAML's old
load(), snakeyaml deserialization) that JSON parsers
don't share — JSON is a strictly smaller attack surface.
The four rules that prevent most YAML bugs
- Always quote ambiguous strings. Country codes,
version numbers, and anything that could be misread as a number,
boolean, or null.
"on": truenoton: true. - Use spaces only, never tabs. Most YAML parsers reject tabs. The error message is rarely helpful.
- Pin the YAML version. Use a parser configured for YAML 1.2 if your data has any of: country codes, boolean- looking strings, leading zeros on numbers.
- Validate before deploying. Lint the file before checking it in. CI failures two minutes after merge are an avoidable expense.
Conversion
Converting in either direction is straightforward — every YAML construct except anchors maps to a plain JSON shape. Anchors get resolved (and any aliases inlined) during conversion.
Paste your YAML on the home page and toggle to JSON to see the converted output.
Reference
- YAML 1.2.2 spec — the current standard.
- RFC 8259 — JSON, the current standard.
FAQ
Is YAML always slower to parse than JSON?
Yes — by roughly 5-50× depending on the parser and content. JSON's grammar is small enough to parse with a tight state machine; YAML's grammar covers anchors, multiple document streams, type tags, and complex scalar styles. For high-throughput wire formats, JSON wins. For human-edited config, the speed gap rarely matters.
Is every JSON file valid YAML?
YAML 1.2 was designed as a superset of JSON, so a valid JSON document is parsed correctly by a YAML 1.2 parser. The reverse isn't true — most YAML features (comments, anchors, multiline strings, etc.) aren't valid JSON.
What's the 'Norway problem'?
In YAML 1.1, the unquoted string 'NO' (Norway's country code) is parsed as the boolean false, along with 'no', 'off', and 'yes'. YAML 1.2 fixed this by recognizing only 'true' and 'false' as booleans. If your parser is on YAML 1.1 (which the original PyYAML defaulted to for years), country codes break. Quote any string that could look boolean.
Should I use YAML for an API response?
No. Use JSON for wire formats — every language has a built-in JSON parser, security tooling expects JSON, and the parse cost is negligible. YAML's value is for files humans edit (CI configs, Kubernetes manifests, Ansible playbooks).
Why does my YAML config behave differently between tools?
The two most common causes: tab vs space indentation (most parsers reject tabs), and YAML 1.1 vs 1.2 type-coercion differences (Norway problem, Yes/No booleans, octal numbers like 010). Lock the version your tool uses and quote ambiguous strings.