Skip to main content
CuteJSON
↑↓ Navigate Enter Select Esc Close

How to diff two JSON documents by what they mean, not how they look

Published 2 min read By Akash Kinkar Pandey

A text diff on JSON reports the wrong thing more often than it reports the right one. Reindent a file, or move a property from the bottom to the top, and a line based diff lights up as dozens of changed lines even though the data is identical. What you actually want to know is whether the values changed, not whether the bytes did.

Using the JSON diff tool

Paste the original document into Before and the changed one into After, then press Compare. Each difference in the result carries the path of the value and both sides of the change, so you are reading “$.b changed from “x” to “y”“ instead of counting plus and minus signs.

Comparing

{"a":1,"b":"x","c":true,"nested":{"n":1.0}}

against

{"b":"y","c":true,"d":"new","nested":{"n":1}}

reports exactly three differences: $.a removed, $.b changed from "x" to "y", and $.d added. Nothing else. $.c is identical and does not appear. $.nested.n does not appear either, because 1.0 and 1 mean the same number.

How objects and arrays are compared differently, on purpose

Objects are treated as unordered, because that is what the JSON specification says they are: a set of name and value pairs with no defined order. Reordering an object’s keys is not a change here, and a diff tool that reported it as one would be reporting on formatting, not on data.

Arrays are compared by position, since that is the only honest reading available. The tool cannot know whether you inserted one element in the middle of a list or rewrote every element after it, so it does not guess. Inserting one item near the start of a long array will show up as many positional changes, which is correct even though it looks surprising the first time.

What counts as equal

1 and 1.0 are the same value, and two different spellings of an escape in a string are the same string. The one place this gets strict is long integers: two twenty digit numbers have to match digit for digit before they are called equal, because a JavaScript double cannot represent them uniquely and a diff that quietly treated two different long IDs as the same number would be actively wrong. All three rules are stated on the page, because a diff that decides silently is one you cannot act on.

Swap sides

If you pasted the documents in the wrong order, Swap sides turns the comparison around without retyping anything, which also flips which side an addition or removal is reported against.

Back to all posts