JSON and YAML describe the same kinds of data: scalars, sequences and mappings. YAML 1.2 is in fact a superset of JSON, so every JSON document is already valid YAML. The choice between them is not about capability. It is about who is going to read and write the file.
The short answer
- Data on the wire — JSON. It is unambiguous, universally supported and fast to parse.
- Configuration a human edits — YAML. Comments, no punctuation noise, and multi-line strings that stay readable.
- Anything security-sensitive from an untrusted source — JSON, or a YAML parser explicitly restricted to core types.
Side by side
{
"service": "checkout-api",
"replicas": 3,
"resources": {
"limits": { "cpu": "500m", "memory": "512Mi" }
},
"tags": ["api", "production"]
}service: checkout-api
replicas: 3
resources:
limits:
cpu: 500m
memory: 512Mi
tags:
- api
- productionThe YAML is shorter and has no closing punctuation to get wrong. It also has no visible structure delimiters, which is why a single wrong indent can silently move a key into the wrong parent.
What YAML adds
- Comments — the single biggest reason configuration files are YAML.
- Multi-line strings —
|preserves newlines,>folds them. Embedding a shell script in JSON is miserable by comparison. - Anchors and aliases —
&defaultsand*defaultslet you reuse a block instead of repeating it. - Multiple documents per file — separated by
---, which is how Kubernetes manifests bundle related resources.
What YAML costs
The Norway problem
In YAML 1.1 — still what many parsers implement — the unquoted scalars yes, no, on, off, y and n are booleans. A country list containing NO for Norway parses as false. Quote your strings.
Version numbers
version: 1.10 parses as the number 1.1. version: 1.2.3 parses as a string, because it is not a valid number. The same field changes type depending on its value — quote it.
Sexagesimal and octal
In YAML 1.1, 12:30 can parse as 750 (base 60), and a leading zero can mean octal, so time: 0930 is not what you expect. Quote it.
Tabs
YAML forbids tab characters for indentation, full stop. An editor that inserts tabs will produce files that fail to parse with an error that points at the wrong place.
Deserialization
Some YAML libraries can instantiate arbitrary objects from tags in the document. yaml.load in older PyYAML was a remote code execution vector; yaml.safe_load exists for this reason. Never parse untrusted YAML with a default loader.
Converting between them
JSON to YAML is lossless — every JSON value has a YAML representation. Use the JSON to YAML converter.
YAML to JSON loses things: comments disappear, anchors are expanded in place, and multi-document files have to be split because JSON holds one root value. Dates and other YAML-specific scalars become strings.
A workable rule
Write configuration in YAML because people edit it. Send data as JSON because machines parse it. Convert at the boundary, and quote anything that could be mistaken for a number or a boolean.