How to compare two JSON files

A text diff flags every reordered key as a change. Compare by structure instead, decide whether array order matters, and only real changes are left.

Published by ThatToolSite

JSON diff compares two JSON documents by their data, ignoring key order and formatting, and lists every change by path. Both documents stay in your browser.

Compare JSON

Why a text diff gives the wrong answer

A JSON object is, in the words of the standard, an unordered collection of names and values. These two documents hold exactly the same data:

{"id": 7, "name": "Ada", "tags": ["admin", "editor"], "plan": "pro"}
{"tags": ["admin", "editor"], "name": "Ada", "plan": "pro", "id": 7}

A text diff compares characters, so it marks the whole line as changed. Pretty-printed, every line would differ. Real changes hide among fake ones, and a reformatted file looks completely rewritten. Comparing by structure fixes this: each value is matched by its path, such as $.plan or $.items[2].price, and only real changes are reported. JSON diff says “No differences” for the pair above.

Compare two JSON files by structure

  1. Paste or open the two versions. The old one on the left, the new one on the right. Both must be valid JSON.
  2. Decide how arrays should be compared. Leave order on for ordered lists; tick Ignore the order of array items for sets.
  3. Read the list of changes. Each line shows the path, the old value and the new value. Copy the summary for a ticket or a review.

If a file won't parse, fix it first in the JSON validator, which shows the line and column of the problem.

Arrays: an ordered list or a set?

Key order never matters in JSON, but array order can. Take document A from above and this new version, where the plan changed and the tags were listed the other way round:

{"plan": "team", "tags": ["editor", "admin"], "name": "Ada", "id": 7}
SettingJSON diff reports
Order matters (default)3 differences: $.tags[0] “admin” removed, $.tags[1] “admin” added, $.plan “pro” → “team”
Ignore the order of array items1 difference: $.plan “pro” → “team”

Both answers are right; they answer different questions. Tags, permissions and IDs are usually sets, so ignore order. Steps of a process, ranked results or the lines of an order are lists, so keep it. For a list of records that should be matched by an id field, sort both arrays by that field first, then compare with order on.

Is 1 the same as "1" or 1.0?

JSON diff compares values by type and by numeric value. That catches the changes that actually break programs, while ignoring ones that don't:

OldNewReported?
"id": 1"id": "1"Yes: a number became a string
"zip": "02134""zip": 2134Yes: and the leading zero is lost
"total": 31.5"total": 31.50No: the same number written differently
1234567890123456789012345678901234567891Yes: compared exactly, not rounded

The last row matters for IDs. Many JavaScript-based tools round both numbers to the same value and call them equal.

Comparing JSON on the command line

With jq installed, you can sort keys and then use an ordinary diff:

diff <(jq -S . old.json) <(jq -S . new.json)

-S sorts the keys of every object. It does not sort arrays, so reordered arrays still show up as changes. Sort a list of records by a field with jq 'sort_by(.id)' before comparing. In Python, json.load(a) == json.load(b) answers yes or no, ignoring key order, but doesn't say what changed.

Timestamps, IDs and other noise

Two API responses often differ in fields that change on every call: updatedAt, request IDs, tokens. They drown out the changes you care about. Remove them from both documents before comparing, for example with jq 'del(.updatedAt, .requestId)', or by deleting the lines by hand in a copy.

For comparing code, config written as YAML or any other text where order and whitespace matter, use the diff checker instead.

Sources