Skip to main content

Guide · 8 September 2026

How to compare two JSON files and see exactly what changed

A raw diff of two JSON files shows hundreds of changed lines when three values moved. Normalise both files first (sort keys, fix indentation), then diff. Browser, jq, Python, VS Code and git methods, plus JSON Patch for machines.

You have two JSON files — yesterday’s API response and today’s, a config before and after a deploy, exports from two environments — and you need to know what actually changed. You drop them into a diff tool and get a wall of red and green: 400 lines changed. Every “change” turns out to be the same object with its keys in a different order, or the same array reindented, and the three values that really moved are buried in the noise.

This is the most common failure when comparing JSON, and it has nothing to do with the diff tool. A diff works line by line; JSON does not care about lines. Until both files are written out the same way, you are comparing formatting, not data.

Fix that first and the comparison becomes trivial. The Diff Checker does the formatting half for you in JSON mode; the rest of this guide covers what normalising means, how to do it with tools you already have, and what to reach for when a human-readable diff is not what you need.

Why two identical JSON documents can diff differently

The JSON specification (RFC 8259) allows a lot of freedom that a line diff punishes:

DifferenceSame data?What a line diff shows
Object keys in a different orderYes — RFC 8259 §4 notes parsers may not even expose orderEvery line of the object as changed
Minified vs pretty-printedYes — whitespace around structural characters is insignificant (§2)One giant line vs many small ones; everything changed
2-space vs 4-space vs tab indentationYesEvery indented line changed
1.0 vs 1, 1e2 vs 100Usually yes — the spec sets no format, only interoperability limits (§6)Line changed
Trailing newline present or missingYesLast line changed
Array elements in a different orderNo — arrays are orderedLines changed (correctly)
Duplicate keys in one objectUndefined — §4 says behaviour is “unpredictable”; most parsers keep the lastDepends on the parser

Everything above the last two rows is noise you eliminate with one step: parse both files, then re-serialise them with the same indentation and keys sorted alphabetically. Two documents with the same data then produce byte-identical text, and the diff shows only real changes.

Two caveats. Array order is real: if an API returns a list in a different order, that is a change, and sorting keys will not hide it. And numbers are only “usually” equivalent — most parsers read 1.0 and 1 into the same double, while jq preserves the literal and can tell them apart. If the exact numeric text matters downstream, compare before normalising as well.

Method 1: in the browser, no install

Open the Diff Checker, paste the original in the left pane and the new version in the right, and set the mode to JSON. Click Format on each side: the tool parses the text and re-emits it with consistent indentation, so the minified-vs-pretty and 2-space-vs-4-space problems disappear before the comparison runs. The side-by-side view scrolls in sync, and in JSON mode the summary bar at the top reports how many root-level keys were added or removed alongside the line counts, so a 2,000-line file with one edited value reads as one changed line rather than two thousand.

What the browser formatter does not do is reorder keys. If your two files came from different serialisers and the key order differs, normalise them with jq or Python (Methods 2 and 3) and paste the outputs into the diff. If a file will not format at all, the JSON Formatter points at the line of the syntax error, which is usually a trailing comma or an unquoted key. Both tools process files in the browser; nothing is uploaded, which matters when the JSON is a production payload.

Very large files — tens of megabytes — are slow in any browser diff; use the command line for those.

Method 2: jq on the command line

jq is a single binary on every platform. Its -S (--sort-keys) flag outputs “the fields of each object with the keys in sorted order”, and by default it pretty-prints with two-space indentation. Feed both normalised outputs to diff:

diff <(jq -S . before.json) <(jq -S . after.json)

Use -u for unified format. PowerShell has no <( ) process substitution, so on Windows write temp files instead:

jq -S . before.json > a.tmp; jq -S . after.json > b.tmp; git diff --no-index a.tmp b.tmp

Three refinements come up constantly. Strip volatile fields before diffing — timestamps, request IDs, ETags — with jq -S 'del(.meta.requestId, .updatedAt)'. Compare only a subtree with jq -S '.data.users'. And when the file is an array of many small records, jq -c '.[]' puts each record on its own line so the diff pairs records instead of fragments; if the array’s order does not matter, '.items |= sort' sorts it, but do that deliberately because it hides real reordering.

Method 3: Python, when jq is not installed

Python’s built-in json.tool does the same normalisation:

python3 -m json.tool --sort-keys before.json > a.tmp
python3 -m json.tool --sort-keys after.json > b.tmp
diff a.tmp b.tmp

Inside a script, json.dumps(obj, sort_keys=True, indent=2) produces the same canonical text, and == on the two parsed objects tells you whether they differ without saying where. For a structural report with paths, the deepdiff package on PyPI walks both objects recursively.

Method 4: VS Code

In the Explorer, right-click the first file and choose Select for Compare, then right-click the second and choose Compare with Selected. From a terminal, code --diff before.json after.json opens the same “file difference editor”. Format each file first (Format Document: Shift+Alt+F, or Shift+Option+F on Mac) so indentation matches; VS Code’s JSON formatter does not sort keys, so if key order differs you still need the jq step. The diff editor’s “ignore trim whitespace” toggle handles trailing-space noise but not structural reordering.

Method 5: make git do it for you

If the JSON files live in a repository, git can normalise them before every diff. Its textconv mechanism runs a program on each side and compares the output. In .gitattributes:

*.json diff=json

And in .git/config or ~/.gitconfig:

[diff "json"]
    textconv = jq -S .
    cachetextconv = true

The gitattributes documentation defines textconv as a program that takes a filename and prints the converted text to stdout, which is exactly what jq -S . does; cachetextconv stores the result so large files are not re-normalised every time. This changes only how diffs are displayed — the stored files are untouched, and a diff produced this way cannot be fed to git apply, so use it for reading, not patching. Hosted pull-request views do not run your local textconv, which is one more reason to commit JSON with a consistent formatter.

When you need a machine-readable answer: JSON Patch

A text diff is for humans. If a program needs to know what changed — to apply the same change elsewhere, store an audit trail, or assert in a test that exactly one field moved — use JSON Patch (RFC 6902). A patch is itself a JSON array of operations, each with an op, a path written as a JSON Pointer (RFC 6901) and, where relevant, a value:

[
  { "op": "replace", "path": "/users/0/email", "value": "new@example.com" },
  { "op": "add",     "path": "/users/0/roles/-", "value": "admin" },
  { "op": "remove",  "path": "/legacyFlag" }
]

The six operations are add, remove, replace, move, copy and test. test asserts that a value is present and of the same JSON type before the rest applies, and the RFC requires that if any operation fails the whole patch fails, so a partial update never lands. Libraries that generate a patch from two documents exist for every major language; the output is deterministic and far easier to review than 400 red and green lines. (JSON Merge Patch, RFC 7396, is a different, simpler format that cannot express array edits or moves — not what you want for comparing files.)

Checklist

  • Both files parsed successfully (a diff of invalid JSON is meaningless — the JSON Formatter will point at the bad line).
  • Same indentation on both sides; keys sorted.
  • Volatile fields (timestamps, IDs, tokens) removed before comparing.
  • Arrays: decided whether order matters, and sorted only if it does not.
  • Numbers: checked whether 1.0 vs 1 matters to the consumer.
  • Need to apply or store the change, not just read it? Generate a JSON Patch instead.
  • Sensitive data? Use a browser-only or local tool; nothing should leave your machine.

Frequently asked questions.

Why does my JSON diff show everything changed when only one value is different?

Because the two files differ in formatting, not just content: one is minified and the other pretty-printed, one uses 2-space indentation and the other 4, or an API serialised the object keys in a different order. A line-based diff sees every line as different. Format both files the same way with sorted keys and the diff collapses to the real change.

Does the order of keys in a JSON object matter?

Not to the data. RFC 8259 notes that parsers differ on whether they even expose member order to your code, so {"a":1,"b":2} and {"b":2,"a":1} are the same object. That is exactly why you should sort keys before comparing: order differences are noise. Array order, by contrast, is significant — [1,2] and [2,1] are different values.

How do I compare two JSON files in VS Code?

Open both, right-click the first in the Explorer and choose Select for Compare, then right-click the second and choose Compare with Selected. From a terminal, code --diff a.json b.json opens the same side-by-side editor. Format both files first (Shift+Alt+F on Windows/Linux, Shift+Option+F on Mac) so indentation differences don't pollute the result.

Can I diff JSON on the command line?

Yes. With jq installed: diff <(jq -S . a.json) <(jq -S . b.json). The -S flag sorts keys and the default output pretty-prints with two-space indentation, so both sides are normalised before diff sees them. Without jq, Python's built-in json.tool does the same: python3 -m json.tool --sort-keys a.json.

What is JSON Patch and when should I use it instead of a diff?

JSON Patch (RFC 6902) expresses changes as a JSON array of operations — add, remove, replace, move, copy, test — each pointing at a location with a JSON Pointer path like /users/0/email. Use it when a program, not a person, needs to consume the difference: applying updates over HTTP PATCH, storing change history, or asserting that a response changed in exactly one place.

Is it safe to paste production JSON into an online diff tool?

Only if the tool runs entirely in your browser. Many online diff sites send both texts to a server. The True Tool Deck diff checker does the comparison in JavaScript on your machine and nothing is uploaded, but if the data includes secrets or personal information, redact them or use a local tool such as jq or VS Code.

Sources

Tools for this job.