Engineering
How to Compare JSON and YAML by Data (and Where the Two Formats Disagree)
JSON and YAML describe the same data model — but not identically. Learn the type-coercion traps, what has no equivalent across formats, each format's real strengths, and how to diff a JSON file straight against a YAML one by value.
JSON and YAML are close relatives. YAML was designed so that any valid JSON document is also valid YAML, and both describe the same underlying shapes: objects (mappings), arrays (sequences), strings, numbers, booleans, and null. That closeness is exactly why comparing them is deceptively hard. The two files can hold identical data and share almost no characters — and they can look nearly identical while meaning different things. This guide covers where the formats genuinely disagree, what each is actually good at, and how to compare them by their data instead of their text.
Why you can't compare JSON and YAML line by line
A line-based text diff is the wrong tool the moment two files use different formats. The same object written as JSON and as YAML shares no punctuation, no indentation, and no line breaks — a text diff reports that every single line changed, which tells you nothing. Here is the same value in both:
{
"service": "auth",
"port": 8080,
"debug": false,
"tags": ["api", "internal"]
}service: auth
port: 8080
debug: false
tags:
- api
- internalThese two files carry exactly the same data. A useful comparison has to parse each side into its data model first, then compare the values — ignoring formatting, quoting, and key order entirely. That's a structural, or data-aware, diff, and it's the only way to answer the question you actually have: do these two configs describe the same thing?
Where JSON and YAML disagree: the incompatibilities
Because YAML is a near-superset of JSON, it's tempting to treat them as interchangeable. They aren't. Some YAML constructs have no JSON equivalent at all, and — more dangerously — some values that look the same parse differently. These are the traps worth knowing before you trust any comparison.
1. Type coercion and the "Norway problem"
JSON is explicit: strings are always quoted, so "false" is a string and false is a boolean, no ambiguity. YAML infers types from unquoted scalars, and the inference has famous edge cases. The classic one: a list of country codes containing Norway's NO. Under the YAML 1.1 rules that many parsers still follow, NO (like no, yes, on, off) becomes the boolean false — not the string "NO" you meant.
countries:
- NO # parses as boolean false under YAML 1.1
- "NO" # parses as the string "NO"
version: 1.10 # parses as the number 1.1 — the trailing zero is gone
zip: 07030 # leading zero can trigger octal parsing in YAML 1.1The YAML 1.2 spec narrowed booleans to just true/false, but which rules apply depends entirely on the parser and its configuration, so you can't assume. The safe habit is to quote any scalar that could be mistaken for a boolean, number, or date. When you compare a JSON file against a YAML file, these coercions are the single most common reason two "identical" configs turn out to differ: one side has the string "NO", the other has the boolean false.
2. null has several spellings in YAML
JSON has exactly one null: null. YAML accepts null, ~, and an empty value all meaning the same thing:
token: null
token: ~
token: # an empty value is also nullA data-aware comparison treats all three as equal to JSON's null. A text diff sees three unrelated lines.
3. Comments, anchors, aliases, and tags have no JSON form
This is the real limitation to understand about cross-format comparison. YAML has features that simply don't exist in the JSON data model, so they can't survive a round trip and won't show up as value differences:
- Comments (
# …) — JSON has none. Convert YAML to JSON and every comment is dropped. - Anchors and aliases (
&name/*name) and merge keys (<<) let YAML reference and reuse a block. Once parsed, they expand into duplicated data — the reference is gone, only the resulting values remain. - Tags (
!!str,!!timestamp, custom!MyType) attach explicit types. JSON has no tag concept. - Multi-document streams — one YAML file can hold several documents separated by
---. A JSON file is a single value.
The honest caveat: a data comparison compares the parsed values. That's the right model for "is this the same config" — but it means it deliberately ignores comments, formatting, and key order, and it sees an anchor as its expanded values rather than as a reference. If a comment or an anchor's structure is what you care about, a data diff won't flag its removal. Comparing the two files as plain text will, at the cost of drowning you in formatting noise. Knowing which question you're asking is the whole game.
4. Duplicate keys and key order
JSON's grammar technically permits duplicate keys (most parsers keep the last), while YAML 1.2 forbids them outright. Neither format's data model treats key order as meaningful — an object is an unordered set of keys — so a correct data comparison ignores reordering. If you reformat a file or a serializer sorts the keys, the data is unchanged and a value diff stays quiet.
5. Numbers, precision, and dates
Both formats can express numbers a 64-bit float can't hold exactly, and most JavaScript-based tools (JSON and YAML alike) parse numbers into doubles — so a very large integer can lose precision on either side. YAML additionally auto-parses unquoted ISO-8601 timestamps into date values, where JSON keeps them as strings. When in doubt, quote it and compare strings.
What each format is actually good at
Neither format is "better" — they're tuned for different jobs. Knowing the trade-offs tells you when a difference between them is a bug and when it's just a format choice.
JSON's strengths
- Unambiguous. Quoted strings and a tiny, strict grammar mean there's essentially one way to read a JSON document. No type-coercion surprises.
- Universal. Every language and virtually every HTTP API speaks JSON natively. It's the default wire format for machine-to-machine data.
- Whitespace-insensitive. Indentation is cosmetic, so JSON is hard to break by accident and safe to minify, stream, and generate programmatically.
- Fast and simple to parse, which matters at API scale.
Its weaknesses are the flip side: no comments, no reuse, heavy punctuation, and verbosity that makes large hand-edited config tedious.
YAML's strengths
- Human-friendly. Indentation instead of braces and unquoted strings make config far easier to read and hand-edit — which is why Kubernetes, GitHub Actions, Docker Compose, and Ansible all use it.
- Comments. You can document why a value is what it is, inline — impossible in plain JSON.
- Reuse. Anchors, aliases, and merge keys let you define a block once and reference it, keeping large configs DRY.
- Multi-line strings via block scalars (
|literal,>folded) read far better than JSON's\nescapes.
Its weaknesses are the ones above: whitespace sensitivity makes it easy to break with a stray space, and its type inference makes it easy to break silently. The very features that make YAML pleasant to write are the ones with no JSON counterpart.
How to compare them by data
Put the two sides through the same three steps and the format differences melt away while the real differences stand out:
- Parse each side into its data model. JSON parses as JSON; YAML parses as YAML. Now you have two in-memory structures, not two blobs of text.
- Normalize. Ignore key order and formatting; treat
null/~/empty as one null; decide up front whether an unquotedNOis a boolean or a string, and quote to remove the ambiguity. - Compare values by path. Walk both structures together and flag every value that changed, every key present on one side and missing on the other. That's your real diff.
You can do this by hand — convert both to the same format first, then diff — but converting is exactly where the coercion and comment-loss traps bite. It's easier to let a tool that understands both formats do the parsing and matching for you.
Doing it in the browser
Our JSON & YAML comparison tool is built for precisely this. Paste a JSON payload on one side and a YAML file on the other — the two sides don't have to be the same format. In Data mode it parses each side and highlights the values that actually differ, ignoring formatting and key order; switch to Syntax mode when you want a literal text comparison instead. It also reads JavaScript object literals, and a one-click convert turns either side into JSON or YAML if you'd rather normalize first. Everything runs locally in your browser, so nothing is uploaded — handy when the config holds secrets or connection strings. If you just need to clean up or convert a single file, the JSON / YAML formatter handles that too.
For the bigger picture on config and code diffing, see the comparison tools for engineers.
Frequently asked questions
Can I compare a JSON file directly against a YAML file?
Yes — but only with a data-aware comparison. Because the two formats share no punctuation, a text diff is useless across them. A structural diff parses each side into its data model and compares the values, so a JSON object and an equivalent YAML mapping read as identical. Our tool does this without making you convert either file first.
Is every JSON file valid YAML?
Essentially yes: YAML 1.2 was designed as a superset of JSON, so a valid JSON document parses as YAML. The reverse isn't true — YAML features like comments, anchors, tags, and multi-document streams have no JSON equivalent, so not every YAML file can be represented as JSON without losing something.
Why do my JSON and YAML files show a difference when they look the same?
Almost always type coercion. An unquoted YAML scalar like NO, yes, 1.10, or a date-looking string gets parsed into a boolean, a number, or a timestamp, while its JSON counterpart is a string. Quote the value on the YAML side and the two will match.
Does converting YAML to JSON lose anything?
It can. Comments are dropped, anchors and aliases are expanded into duplicated data (the reference is lost), explicit tags may not survive, and only the first document of a multi-document stream is kept. The data is preserved; the YAML-specific structure around it is not. That's why comparing by data — rather than converting and comparing text — avoids introducing changes of its own.
Which should I use, JSON or YAML?
Use JSON for machine-to-machine data and APIs, where its strictness and universality are exactly what you want. Use YAML for configuration that humans read and edit, where comments and readability pay off — just quote anything ambiguous. Many teams use both, which is precisely why comparing across the two comes up so often.