YAML vs JSON: Differences, Gotchas, and When to Use Each
YAML and JSON describe the same kinds of data — maps, lists, strings, numbers, booleans, null. In fact, every JSON document is valid YAML, because YAML is a superset. The difference is ergonomics and a handful of YAML quirks that can turn a config file into a debugging session. Here's a practical comparison.
The surface difference: punctuation vs whitespace
JSON uses braces, brackets, quotes, and commas. YAML uses indentation and dashes, drops most of the punctuation, and allows comments:
{
"name": "api",
"replicas": 3,
"ports": [80, 443]
}
# the same data in YAML
name: api
replicas: 3
ports:
- 80
- 443
For a human editing a config file, YAML is easier to read and write. For a machine exchanging data over the wire, JSON's rigid, brace-delimited structure is easier to parse and far harder to get subtly wrong.
What YAML adds
- Comments (
# like this) — the single biggest reason config files use YAML. JSON has no comments at all. - Anchors and references (
&name/*name) — define a block once and reuse it, reducing repetition in large configs. - Multi-line strings with
|(preserve newlines) and>(fold into spaces) — much nicer than JSON's\n-laden one-liners. - Less visual noise — no trailing-comma errors, no quote-everything requirement.
YAML's sharp edges
This is where YAML's "helpfulness" becomes a liability. Because it tries to infer types from unquoted values, it guesses wrong in some famous ways:
The Norway problem. YAML 1.1 interprets several unquoted words as booleans:
countries:
- NO # ← becomes the boolean false, not the string "NO"
- SE
- FR
NO, YES, ON, OFF, TRUE, FALSE (in various cases) can all be coerced to booleans. The country code for Norway becomes false. The fix is always to quote strings that could be misread: "NO".
Sexagesimal and leading zeros. In YAML 1.1, 12:30 can parse as a base-60 number, and a value like 010 may be read as octal. A version string or a ZIP code like 08544 can lose its leading zero or change value entirely. Quote them.
Significant whitespace. A single misaligned space changes the structure, and tabs are forbidden for indentation. The error messages are often unhelpful about where the indentation went wrong.
JSON has none of these ambiguities: a string is a string because it's in quotes, and there's exactly one way to write it.
A quick comparison
| JSON | YAML | |
|---|---|---|
| Comments | no | yes |
| Syntax | braces & commas | indentation |
| Type coercion surprises | none | yes (Norway, octal, dates) |
| Multi-line strings | escaped \n |
` |
| Reuse (anchors) | no | yes |
| Best for | APIs, data interchange | human-edited config |
| Parsing strictness | strict, simple | lenient, complex |
When to use which
- JSON for anything a program produces and consumes: API payloads, logs, data files, message queues. Predictable, universal, no surprises.
- YAML for files humans edit: CI pipelines, Kubernetes manifests, app config. The comments and readability pay off — just quote ambiguous values.
A common workflow is authoring config in YAML but needing JSON for a tool that only speaks JSON (or vice versa). The YAML ↔ JSON converter does the round-trip in your browser; for a quick one-direction conversion you can go straight to YAML → JSON or JSON → YAML.
Takeaways
- Every JSON doc is valid YAML; YAML adds comments, anchors, and readability.
- YAML's type inference causes real bugs — quote any string that could look like a boolean, number, or date (the Norway problem).
- Use JSON for machines, YAML for humans, and convert between them when a tool forces your hand.