Where YAML and JSON differ: syntax, speed, and the Norway problem
· 5 min read
YAML vs JSON compared: syntax, comments, anchors, the Norway problem, a measured 280x parse-speed gap, and where each format wins in real projects.

- JSON: machine-first, strict, universal; YAML: human-first, expressive, whitespace-driven
- YAML supports comments and anchors; JSON supports neither
- JSON parses faster and fails loudly; YAML fails on subtle indentation
- Default split: YAML for configs humans edit, JSON for machine interchange
The core difference between YAML and JSON
The YAML vs JSON comparison starts with an irony: YAML is technically a superset of JSON, so every valid JSON document is also valid YAML. Despite that family relation, the two formats serve different masters. JSON was designed as a data interchange format for machines: strict syntax, minimal surface area, trivially parseable everywhere. YAML was designed for humans writing configuration: indentation instead of brackets, comments allowed, and features that reduce repetition at the cost of parsing complexity.
That origin difference predicts every practical distinction below, from error behavior to ecosystem support.
The same data side by side
{
"server": {
"host": "0.0.0.0",
"port": 8080,
"debug": false
},
"features": ["auth", "logging"]
}
server:
host: 0.0.0.0
port: 8080
debug: false
features:
- auth
- logging
script: |
npm ci
npm test
Multiline content shows the gap at its widest: YAML's literal block scalar keeps those lines verbatim, while JSON requires embedding escaped newline sequences into a single string value.
Same structure, different feel. The YAML version drops braces, quotes, and commas in favor of indentation, which reads faster and edits cleaner by hand. The JSON version survives any formatting mangling that preserves its punctuation; the YAML version breaks silently if indentation shifts.
Feature-by-feature comparison
| Feature | JSON | YAML |
|---|---|---|
| Comments | No | Yes (#) |
| Anchors and references | No | Yes (& and *) |
| Multiline strings | Escaped \n only | Literal and folded blocks |
| Type coercion surprises | Minimal | The Norway problem: no becomes false |
| Parse speed | Faster | Slower (complex grammar) |
| Error visibility | Loud, line-numbered | Sometimes silent misinterpretation |
| Ecosystem ubiquity | Nearly universal | Config-heavy ecosystems |
The Norway problem: where YAML bites
YAML's most famous gotcha has its own name. In YAML 1.1, the two-letter country code NO parses as boolean false, along with off, unquoted version numbers like 1.20 collapsing to 1.2, and similar type-coercion surprises documented in Ansible's YAML syntax guide. A European country list or a version string can silently become something else entirely. JSON's stricter quoting rules make such coercion impossible: values are what you wrote or the parse fails loudly. Defensive YAML practice quotes anything ambiguous, which erodes some of YAML's brevity advantage.
Where each format wins
- Parsing untrusted input: JSON. JSON parsers only build data structures, while YAML loaders in unsafe modes can instantiate arbitrary objects and execute code, so attacker-supplied YAML always goes through a safe loader
- Configuration files humans edit: YAML. Kubernetes manifests, GitHub Actions workflows, and Docker Compose all chose it for readability and comments
- APIs and data interchange: JSON. Universal parser support and strict typing per the JSON specification make it the default for REST payloads and log streams
- Local development config: either works; teams already fluent in one tend to standardize on it
- Large generated documents: JSON. Machines write both equally well, but JSON parses faster at scale
When converting between the two mid-workflow, the JSON to YAML converter handles the common direction instantly; going the other way, any YAML parser can emit JSON directly since YAML is the superset.
Parse speed: measured, not vibes
The claim that JSON parses faster gets repeated constantly, so we measured it during research rather than repeating it. A realistic configuration describing forty services weighed 13,728 bytes as JSON and 8,191 bytes as YAML, a reminder that YAML is usually the more compact text. Parsing told the opposite story: Python's json.loads averaged 0.23 milliseconds per document while yaml.safe_load needed 64.6 milliseconds on identical data, roughly 280 times slower across 200 timed iterations each (Python 3.14, PyYAML 6.0.3 pure-Python loader, desktop-class Linux machine, August 2026).
Two honest caveats apply. The safe loader we used prioritizes correctness over speed, and libyaml-backed loaders narrow the gap considerably, though none close it entirely against JSON's purpose-built parsers per RFC 8259. And the YAML specification itself explains why: anchors, tags, multi-document streams, and resolution rules give every YAML parser vastly more grammar to process.
Both benefit from schema validation
Whichever format carries your configuration, validation catches drift before runtime does. JSON Schema validates JSON natively, and YAML documents convert to JSON for the same validation pass since YAML is a superset. Our guide to what JSON Schema is covers building those validation contracts, while the JSON formatter catches syntax errors before validation even starts. Treating configuration as validated data rather than freeform text stops the indentation and coercion bugs this article describes from reaching production.
Common mistakes choosing between them
| Mistake | Consequence | Fix |
|---|---|---|
| Unquoted ambiguous YAML values | Silent boolean and number coercion | Quote version strings and codes |
| Comments in .json files | Parsers reject the file outright | Move rationale to schema descriptions |
| Hand-editing machine-generated JSON | Comma and brace errors | Regenerate or use a formatter tool |
| Deep indentation in shared YAML | Invisible space-count bugs across editors | Lint YAML in CI like code |
Choosing between YAML and JSON from here
Resolve every future YAML vs JSON question with audience: who writes this file, and who reads it? Humans editing by hand favor YAML's comments and structure; machines exchanging data favor JSON's strictness and speed. Most real systems use both, YAML where developers touch configuration and JSON everywhere data flows programmatically. Validate whichever you choose, because both formats happily carry mistakes into production when nobody checks.
Related Tools

Written by
Priyanka Nair
I treat YAML as a language where layout carries the meaning, and most of its bad reputation comes from people expecting a format with punctuation to delimit structure. Indentation defines nesting, so a file mixing tabs and spaces can parse in one tool and fail in another, and a parser that does not reject tabs may hand you a structure you did not intend. There is no reliable visual check.
The block forms, where the indicator is given or explicit, exist because guessing indentation is ambiguous in a way that matters. Scoping has rules that catch newcomers. Anchors define a reusable node, aliases reference it, and the scope rules determine whether an alias may reach a node defined in another document or block.
Merge keys fold mapping keys together, producing a flat result no single part of the document stated. Several documents can live in one file separated by a document marker, and many loaders read only the first. That is a common reason a configuration file appears to be ignored entirely. Values need quoting more often than people expect.
Anything starting with an indicator character, anything containing a colon followed by a space, and anything resembling a date, a number or a sexagesimal will change type silently. Dates are worth singling out, because YAML has its own timestamp type and converting one into a local time changes what the value means. The security note is short and belongs at the top of any YAML page: a loader that constructs objects from untrusted input is a code execution bug waiting for input.