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 JSONWhy 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
- Paste or open the two versions. The old one on the left, the new one on the right. Both must be valid JSON.
- Decide how arrays should be compared. Leave order on for ordered lists; tick Ignore the order of array items for sets.
- 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}| Setting | JSON diff reports |
|---|---|
| Order matters (default) | 3 differences: $.tags[0] “admin” removed, $.tags[1] “admin” added, $.plan “pro” → “team” |
| Ignore the order of array items | 1 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:
| Old | New | Reported? |
|---|---|---|
"id": 1 | "id": "1" | Yes: a number became a string |
"zip": "02134" | "zip": 2134 | Yes: and the leading zero is lost |
"total": 31.5 | "total": 31.50 | No: the same number written differently |
12345678901234567890 | 12345678901234567891 | Yes: 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
- RFC 8259, section 1. An object is an unordered collection of name/value pairs
- jq manual. --sort-keys / -S sorts the fields of each object