JSON vs YAML: when to use which
These two formats describe the same shapes — maps, lists, strings, numbers, booleans, null — and YAML is very nearly a superset of JSON. The interesting differences aren't about capability. They're about who's reading the file, whether you need comments, and how much implicit type-guessing you're willing to tolerate.
The same data, twice
A small service config in JSON:
{"name":"api","port":8080,"debug":false,"hosts":["a.example.com","b.example.com"]}
The same thing in YAML:
name: api
port: 8080
debug: false
hosts:
- a.example.com
- b.example.com
No braces, no quotes, no trailing-comma hazards — structure carried by indentation. For a human editing a config by hand, that's a genuine improvement. For a machine exchanging a million messages a day, it's irrelevant, and the braces are a feature.
Where JSON wins
- Ubiquity. Every language parses JSON out of the box. No dependency, no version question.
- Speed and simplicity. The grammar fits on a page. Parsers are fast and boring, which is exactly what you want on a hot path.
- Unambiguous types. If it's quoted it's a string, full stop. No parser guesses at your intent.
- The web already speaks it. APIs, browser
fetch, logs, NoSQL documents — JSON is the lingua franca of data interchange. - Whitespace doesn't matter. Minify it, reflow it, paste it through a chat window — it survives.
Where YAML wins
- Comments. JSON has none, and for a config file that's a serious loss. YAML's
#comments let you explain why a value is what it is. - Readability at depth. Deeply nested structures stay legible without a wall of closing brackets.
- Multi-line strings. Block scalars (
|to keep newlines,>to fold them) beat embedding\nescapes in a JSON string — a real win for scripts and certificates. - Anchors and aliases.
&nameand*namelet you define a block once and reuse it, reducing duplication in large configs. - Cleaner diffs. Adding a line to a YAML list touches one line; in JSON it often touches two, because the previous line gains a comma.
The YAML traps
YAML's convenience comes from guessing types for unquoted values, and the guessing is where it bites.
The Norway problem
The famous one. Under YAML 1.1, the unquoted tokens yes, no, on, off, true and false are all booleans. So a list of country codes:
countries: [US, GB, NO]
…quietly parses NO — Norway — as the boolean false. The same class of bug turns a ON (Ontario) or a spreadsheet's Y/N column into booleans.
YAML 1.2 narrowed the core schema so only true/false are booleans, which fixes it — but which behavior you get depends entirely on your parser, and several widely used ones still default to 1.1 semantics. The converter on this site follows YAML 1.2, so no stays the string "no".
Version strings become numbers
This one is version-independent and catches people constantly:
version: 1.10
That's a valid float, so it parses as the number 1.1 — and your "version 1.10" silently becomes "1.1". Anything that looks numeric but isn't semantically a number (versions, ZIP codes, phone numbers, part codes with leading zeros, git SHAs that happen to be all digits) needs quoting: version: "1.10".
Indentation is load-bearing
Tabs are illegal as indentation in YAML. Mixing them in — or getting a nesting level off by one space — changes the meaning of the document or fails the parse, sometimes far from the actual mistake. In JSON, indentation is decoration; in YAML, it's syntax.
The surface area is large
YAML supports anchors, aliases, merge keys, multiple documents in one stream, explicit type tags, and several string styles. That power carries a cost: more to learn, more parser differences, and historically more security exposure — loading untrusted YAML with a language's "full" loader has led to remote code execution in several ecosystems. Always use the safe/pure loader (yaml.safe_load and equivalents) for input you didn't write.
A rule of thumb
- Machines talking to machines? JSON. APIs, message queues, log lines, storage formats.
- Humans editing a file by hand? YAML — especially if comments matter. CI pipelines, Kubernetes manifests, application config.
- Both? Author in YAML, convert to JSON at build time. You keep the comments and readability where people work, and hand machines the simpler format.
And if you want JSON with comments specifically, JSONC (JSON with // and /* */) is a lighter step than adopting YAML wholesale — it's what VS Code uses for its settings. The JSON formatter here accepts JSONC input and strips the comments when it formats.
Converting between them
Because YAML is essentially a superset, JSON → YAML is lossless and mechanical. Going the other way loses whatever YAML-specific expressiveness you used: comments disappear (JSON has nowhere to put them), anchors are expanded or rejected, and multi-document streams don't fit in a single JSON value.
A practical habit when converting YAML to JSON is to check the result for values that changed type on you — a quoted "1.10" that arrived as 1.1, or a country code that became false. Reading the JSON output is the fastest way to see exactly what your YAML actually meant, as opposed to what you thought it said.
Try the conversion
The JSON ↔ YAML converter on this site runs entirely in your browser and shows both documents side by side, so you can paste a config and immediately see how each value was typed. It follows YAML 1.2, supports block scalars and comments on input, and reports clear errors for the constructs it won't guess at. Nothing you paste is uploaded anywhere.