JSON and YAML describe the same kinds of data — maps, lists, strings, numbers, booleans and null — but they were designed for different readers. This guide compares them feature by feature and explains the traps that make YAML surprising.
The short answer
Use JSON when machines are the main readers: HTTP APIs, message payloads, data stored in databases, lock files and anything generated by code. It is small, strict, fast to parse and supported by every language’s standard library.
Use YAML when people edit the file by hand and need comments: Kubernetes manifests, GitHub Actions and GitLab CI pipelines, Ansible playbooks, Docker Compose files and application configuration. Its indentation-based syntax is easier to scan and diff, at the cost of a much larger and more surprising specification.
Since YAML 1.2, nearly every JSON document is also valid YAML, so a YAML parser can read JSON. The reverse is not true.
Side-by-side comparison
- Specification size: JSON (RFC 8259 / ECMA-404) fits on a few pages. The YAML 1.2 specification runs to dozens of pages of grammar.
- Comments: JSON has none. YAML supports
#comments anywhere a line can end. - Structure: JSON uses
{},[], commas and quotes. YAML uses indentation (spaces only — tabs are forbidden for indentation) and also accepts JSON-style flow collections. - Strings: JSON strings are always double-quoted. YAML strings can be plain (unquoted), single-quoted, double-quoted or written as multi-line block scalars.
- Types: JSON has exactly six value types. YAML resolves plain scalars to types by pattern, which is where most surprises come from, and supports explicit tags such as
!!str. - Reuse: YAML has anchors (
&base) and aliases (*base), plus the widely supported<<merge key. JSON has nothing equivalent. - Multiple documents: a YAML stream can hold several documents separated by
---. JSON is one value per document (see JSON Lines for streams). - Speed: JSON parsers are typically many times faster than YAML parsers on the same data.
Here is the same data in both:
{"service": "checkout", "replicas": 3, "features": ["payments", "refunds"], "debug": false}
# checkout service
service: checkout
replicas: 3
features:
- payments
- refunds
debug: false
Where YAML bites: implicit typing
An unquoted YAML value becomes a string, number, boolean or null depending on what it looks like, and the rules changed between YAML 1.1 and 1.2. Many popular parsers, including PyYAML and older Ruby and Go libraries, still implement 1.1 behaviour.
- The Norway problem: in YAML 1.1,
NO,no,off,n,yes,onandyare booleans. A list of country codes containingNOturns Norway intofalse. YAML 1.2’s core schema only recognisestrueandfalse. - Version numbers:
version: 3.10is the float 3.1. Quote it:"3.10". - Octal: under 1.1,
mode: 0755is read as the integer 493; YAML 1.2 writes octal as0o755and treats a leading zero as decimal. - Sexagesimal: YAML 1.1 reads
time: 1:30as the base-60 number 90. - Null:
~,nulland an empty value all mean null, sopassword:with nothing after it is not an empty string.
The defensive rule is simple: quote any string that could be mistaken for something else, and know which YAML version your parser speaks. The PasteKit YAML formatter has a YAML version option so you can see how 1.1 and 1.2 read the same file.
JSON has none of this. "NO" is a string, 3.10 is a number, and the only literals are true, false and null.
Security and robustness
JSON parsers build plain data structures and nothing else. Some YAML libraries can construct arbitrary language objects from tags — Python’s yaml.load without a safe loader and Ruby’s unsafe_load are the classic examples — which has led to remote code execution bugs when untrusted YAML was parsed. Always use the safe loading function your library provides.
Anchors and aliases enable a denial-of-service trick known as the “billion laughs” or alias bomb: a few lines of nested aliases expand into billions of nodes. Robust parsers cap alias expansion; check that yours does before accepting YAML from users.
YAML’s whitespace sensitivity also creates quiet errors. Indenting a key two spaces too far moves it into a different map without any syntax error. A formatter that re-indents the file consistently makes such mistakes visible in review.
Converting between them
Going from JSON to YAML is lossless: every JSON value has a YAML representation, and a good converter quotes strings like "NO" or "3.10" so they survive a round trip. Going from YAML to JSON loses what JSON cannot express: comments disappear, aliases are expanded into copies, and multi-document streams must become an array or separate files.
Both PasteKit converters preserve key order, quote ambiguous strings such as "NO" on the way to YAML, and keep large integers digit for digit. Try JSON to YAML and YAML to JSON; both run in the browser.
On the command line, yq does for YAML what jq does for JSON, and both can convert: yq -o=json file.yaml prints JSON, and yq -P file.json prints YAML. When the files contain credentials, prefer such local tools or a converter that runs in the browser over a service that uploads them.
A practical pattern used by many teams: author configuration in YAML for readability, validate it against a JSON Schema (YAML maps onto the JSON data model, so the same schema works), and ship JSON to the services that consume it.
Frequently asked questions
Is YAML a superset of JSON?
Since YAML 1.2, almost every JSON document is valid YAML. Rare edge cases, such as some escape sequences and very long keys, behave differently, and YAML 1.1 parsers are less compatible.
Which is faster to parse?
JSON, usually by a wide margin, because its grammar is tiny and parsers are highly optimised. For hot paths such as API traffic, JSON is the safer choice.
Why does YAML turn NO into false?
YAML 1.1 treats yes/no/on/off and their variants as booleans. YAML 1.2 dropped that rule, but many parsers still default to 1.1. Quote such values to be safe.
Can I add comments to JSON?
Not in standard JSON. JSONC and JSON5 allow comments, and many tools such as VS Code and TypeScript accept them in their own config files.
Does Kubernetes accept JSON instead of YAML?
Yes. The Kubernetes API speaks JSON, and kubectl accepts manifests in either format.