About the JSON Diff Checker
A plain text diff of two JSON files is noisy. Different indentation, keys in another order or a reformatted file make everything look changed. The JSON Diff Checker compares the data itself, so you only see the values that really differ.
Paste the original JSON on the left and the changed JSON on the right. You get a table of every difference, each with its path, such as stock.store or users[0].age, and the value before and after. Changes are sorted into added, removed, changed and type changed, so a number that became a string stands out right away.
It is useful for checking API responses between versions, reviewing config changes, debugging tests and comparing exports. Numbers are compared exactly, even long IDs. Everything runs in your browser, so neither document leaves your device.
How to use it
- Paste the originalPut the older or expected JSON in the Original JSON box, or use Open to load a file. You can also drop a file onto either box.
- Paste the changed versionPut the newer or actual JSON in the Changed JSON box. Each box shows "valid" or "invalid" as you type.
- Read the differencesThe table lists every change with its path and both values. The heading shows the total number of differences.
- Adjust the comparisonTurn on Ignore array order when the order of list items does not matter. Turn on Show unchanged values to see the matching values too.
- Share the resultCopy report gives a short text summary with + for added, - for removed and ~ for changed values. Download saves it as json-differences.txt.
Key features
Compares data, not text
Whitespace, indentation and the order of keys in objects are ignored. Only real changes to values are listed.
Exact paths
Every row shows where the change is, like price, tags[2] or stock.store, in the same style you would use in JavaScript.
Type changes flagged
When a value changes type, such as true becoming "yes" or 97204 becoming "97204", it is marked Type changed instead of just Changed.
Smart array matching
An item inserted into the middle of a list shows up as one addition, not as a change to every item after it.
Exact numbers
Long IDs are compared digit by digit, so 12345678901234567890 and 12345678901234567891 are reported as different.
Private by design
Both documents are compared in your browser. Nothing is uploaded or stored.
Examples
Comparing two product records
The Sample button loads these two versions of a product:
{"id": 42, "name": "Desk lamp", "price": 39.9, "tags": ["home", "light"], "stock": {"warehouse": 12, "store": 3}, "active": true}
{"id": 42, "name": "Desk lamp LED", "price": 34.9, "tags": ["home", "light", "sale"], "stock": {"warehouse": 12}, "active": "yes", "color": "black"}
The result shows 6 differences, and the status line reads 3 changed · 2 added · 1 removed:
| Change | Path | Before → after |
|---|---|---|
| Changed | name | "Desk lamp" → "Desk lamp LED" |
| Changed | price | 39.9 → 34.9 |
| Added | tags[2] | "sale" |
| Removed | stock.store | 3 |
| Type changed | active | true → "yes" |
| Added | color | "black" |
The type change counts toward "changed" in the status line. Copy report turns the same result into plain text:
~ name: "Desk lamp" -> "Desk lamp LED"
~ price: 39.9 -> 34.9
+ tags[2]: "sale"
- stock.store: 3
~ active: true -> "yes"
+ color: "black"
What counts as a difference
| Original | Changed | Result |
|---|---|---|
{"a":1,"b":2} | {"b":2,"a":1} | Equal |
[1.0, 1e2] | [1, 100] | Equal |
{"zip": 97204} | {"zip": "97204"} | Type changed |
{"a": null} | {} | Removed |
Key order and the way a number is written do not matter. A missing key is not the same as a key set to null.
Array order
Compare {"tags": ["a", "b", "c"]} with {"tags": ["c", "a", "b"]}. By default you get 2 differences: "c" added at tags[0] and "c" removed from tags[2]. Turn on Ignore array order and the result is No differences, because both lists hold the same items.
An item inserted into a list
Original: [{"id":1},{"id":2},{"id":3}]. Changed: [{"id":1},{"id":4},{"id":2},{"id":3}]. The checker reports exactly 1 difference, {"id":4} added at [1], and does not mark the items after it as changed.
Tips
- Put the expected or older version on the left. "Removed" then means something disappeared in the new version, and "Added" means it is new.
- Use Format both to indent the two inputs. It does not change the comparison, but it makes the boxes much easier to read.
- For lists where order has no meaning, like tags, permissions or IDs, turn on Ignore array order to hide moves and see only real additions and removals.
- Watch for Type changed rows when comparing API versions. A number turning into a string or an object turning into null is the kind of change that breaks clients.
- Paste the copied report into a pull request, a ticket or a chat message. Its +, - and ~ lines read well in plain text.
Common mistakes and limits
- Expecting key order to countJSON objects have no meaningful key order, so {"a":1,"b":2} and {"b":2,"a":1} are the same data. Use Text Compare if you need a line-by-line text comparison.
- Leaving Ignore array order on by mistakeWith it on, a list that was reordered shows no differences. If the order of items matters, as with steps or rankings, keep it off.
- Comparing invalid JSONBoth sides must be valid JSON. The status line shows which side has the error and where, and the comparison starts once both are valid.
- Forgetting about duplicate keysIf an object has the same key twice, only the last value is kept, as most JSON parsers do. Duplicates in the input do not show up as a difference.
- Reading cut-off values as the full valueLong values are shortened to 160 characters in the table, and only the first 2,000 rows are shown. Copy report always includes every difference in full.