How to compare two JSON files
Why a plain text diff fails on JSON, what a real JSON comparison does, and how to read the result.
Two JSON files. One works, one does not. You need the difference, and you need it in seconds.
A plain text diff will not give it to you. This page says why, and what to do instead.
Why a text diff fails
Take these two files:
{"name": "Ada", "age": 36}
{
"age": 36,
"name": "Ada"
}
They hold exactly the same data. The order of the keys in an object means
nothing in JSON, and white space means nothing. diff reports that every line
changed.
The opposite also happens. A text diff on a file that was reformatted shows thousands of changed lines and hides the one value that really changed.
A JSON comparison works on the data, not on the characters. It must know that:
- The order of keys in an object does not matter.
- White space does not matter.
- The order of items in an array does matter.
1.0and1are the same number."1"and1are not the same, because one is text.
The hard part: lists
Objects are easy. You match the keys and you are done.
Lists are the real work. Add one item at the front of a list of 10 000, and a naive comparison by position reports 10 000 differences: every item moved by one place.
A good comparison finds the items that match, in order, and reports only the
one that was added. The usual method is the same one diff uses for lines of
text, applied to the items of the list.
This tool does three steps:
- Cut away the items that are the same at the start of both lists.
- Cut away the items that are the same at the end.
- Match what is left, item by item.
Steps 1 and 2 cost almost nothing and solve the common cases — an item added, an item removed, the end of a list that grew. Step 3 only runs on the small part in the middle.
Doing it in this viewer
- Open the first file.
- Tools → Compare with another file… and choose the second one.
- A Diff tab appears.
The list shows one line for each difference:
| Column | What it holds |
|---|---|
| Path | Where the difference is, as a JSONPath |
| This document | The value in the file you opened |
| The other document | The value in the file you compared |
Each line is marked: green for a value only in the second file, red for a value only in the first, blue for a value that changed. The four buttons at the top filter by kind, so you can see only what was added, or only what was removed.
Click a line and the tree moves to that place, so you can see the value in its context.
Doing it on the command line
With jq, sort the keys first so the text diff has a chance:
diff <(jq -S . a.json) <(jq -S . b.json)
-S sorts the keys, and jq normalises the white space. This handles the key
order problem, but it still reports a whole block when one item moves in a
list, and it still shows you text rather than paths.
For a proper answer on the command line, a dedicated tool such as json-diff
or dyff does the job.
Reading the result
A long list of differences usually means one of three things.
One root cause, many lines. A single changed identifier near the top can move every item in a list below it. Fix the first line in the list and read the result again.
A reformat. If the only differences are in numbers, such as 1.0 against
1, or in text that holds the same characters, a program on the way rewrote
the data.
A real change. Filter to Changed and read the paths. A pattern in the paths tells you which part of the system changed.
A common trap: the order of a list
{"tags": ["a", "b"]}
{"tags": ["b", "a"]}
These are different in JSON, and the comparison reports it. But in many systems a list of tags is really a set, and the order carries no meaning. The format cannot know that; only you can.
If the order does not matter to you, sort the lists before you compare:
jq -S '.tags |= sort' a.json > a-sorted.json
Comparing an API answer before and after a change
This is the most useful habit on this page. Before you change a service, save the answer. After the change, save it again and compare.
curl -s https://api.example.com/v1/users/1 > before.json
# deploy the change
curl -s https://api.example.com/v1/users/1 > after.json
Then open before.json in the viewer and compare it with after.json. A
field that quietly disappeared, or a number that became text, shows up at
once. Those are the changes that break the people who use your service, and
they are the ones that tests often miss.
Try it on your own file. The tool runs in your browser. Nothing is uploaded, and nothing is stored on a server.
Open the JSON ViewerRead next
How to turn JSON into CSV
The rules for flattening nested data into columns, the traps, and three ways to do it.
How to turn JSON into a TypeScript interface
Get types from a real API answer in seconds, and know what the generated types cannot tell you.