DiffScope

Diffing JSON and YAML the Right Way

5 min readUpdated September 2026
A laptop showing structured data

Comparing two API responses or two config manifests should be easy, but structured data has a habit of exaggerating. A pretty-printer with different settings, keys in a different order, or a stray change in indentation can make two essentially identical documents look wildly different in a plain text diff. A little preparation makes the comparison honest.

Format both sides first

A line diff can only compare lines, so a minified JSON blob on one side and a pretty-printed one on the other will look completely different even when the data is identical. The fix is to normalise the presentation before comparing: pretty-print both documents with the same indentation so each key and value sits on its own line. Now the diff operates on the real structure, and a changed value shows up as a single changed line instead of one giant line replacing another.

The same applies to YAML: consistent indentation and quoting on both sides keeps the diff meaningful. Since YAML is a superset of JSON, converting both to formatted JSON is one reliable way to compare them on equal footing.

Tame key ordering

In JSON objects and most YAML mappings, the order of keys carries no meaning — {"a":1,"b":2} and {"b":2,"a":1} are the same data. But a text diff does not know that; if one system serialises keys alphabetically and another preserves insertion order, the diff will show a storm of moves that mean nothing. Sorting keys consistently on both sides before comparing removes this false signal and leaves only genuine additions, removals and value changes.

Arrays are the exception: their order usually is meaningful, so do not sort them. Reordering a list of steps or a sequence of middleware genuinely changes behaviour, and you want the diff to show that.

YAML says the same thing several ways

JSON offers a little formatting freedom; YAML offers a great deal. The same mapping can be written in block style over several lines or in flow style on one. A string can be bare, single-quoted or double-quoted. A long value can use a literal block with a pipe, which keeps its newlines, or a folded block with a greater-than sign, which turns them into spaces, and each carries a chomping indicator deciding what happens to the final newline.

Anchors and aliases go further still: define a block once with an anchor, reuse it by name with an alias, and fold it into another mapping with a merge key. Two files that parse to exactly the same data can therefore share almost no lines of text. Parsing both and re-emitting them under one set of conventions — or converting both to formatted JSON — is the only dependable way to put them side by side.

The values that quietly change type

YAML infers a type from unquoted text, and the inference has famous edge cases. Under the YAML 1.1 rules most parsers still follow, no, yes, on and off are booleans, so a country code of NO becomes false — the Norway problem. A version written as 1.10 is a number and loses its trailing zero on the way back out. A zero-padded value such as 022 can be read as octal, and an unquoted value containing a colon or a hash may be parsed as a mapping or cut short as a comment.

This is one place where a plain text diff earns its keep. Put quotes around a value and the data changes type while the diff shows only two quotation marks: a tiny edit, easy to approve, with real consequences. Read a change in quoting as a change in meaning rather than in formatting.

What a structural comparison cannot see

A structural comparison parses both documents and reports differences as paths — replicas changed from 3 to 5 — which makes it immune to key order, indentation and style. It is the right answer to the question of whether two documents mean the same thing. It is not the whole answer, because parsing throws away things the file genuinely contains.

Comments are the obvious loss: they are not part of the data model, so a round trip through most libraries deletes them, and in configuration a comment is often the only record of why a value is what it is. Duplicate keys are the subtle one. Both specifications treat them as invalid, yet many parsers quietly keep the last occurrence, so a document with a key defined twice compares as perfectly fine once parsed, while the text diff shows the second definition shadowing the first. Compare the parsed structure to learn what changed in meaning, and compare the text to review what you are actually committing.

Read the result

With both documents formatted and their keys ordered the same way, paste them into DiffScope and the comparison becomes trustworthy. Word-level highlighting is especially handy here: when a single nested value changes from true to false or one number is off by a digit, it lights up inside the line while the surrounding structure stays quiet.

For a final check, turn on ignore-whitespace to absorb any last indentation differences, and download the patch if you need to attach the change to a review or a ticket. The result is a clean, honest picture of how the two structures actually differ.

The takeaway

Before diffing JSON or YAML, pretty-print both sides and sort object keys the same way — but leave arrays alone. Then word-level highlighting makes a single flipped boolean or changed number obvious, and ignore-whitespace mops up the rest.

Related tool
DiffScope · Compare tool

Open the tool and try it now