Skip to content
ToolBoxGeniehome

JSON Diff

Developer Tools · Added

A line-based diff is the wrong tool for JSON: it reports two changes when you reorder keys and none at all when a number quietly becomes a string. This one parses both sides and walks the values, so what it reports is what actually differs.

Compare arrays

Element 0 against element 0. Right for a fixed tuple or an ordered log — but inserting one element at the front reports every later element as changed.

How to use the json diff

  1. 1Paste the original document on the left and the new one on the right.
  2. 2Choose how arrays should be compared — by position, or as an unordered set.
  3. 3Read the change list: each row gives the path, the old value and the new one.
  4. 4Look at the type-changed rows first; those are the ones that break the consumer.

Examples

Reordered keys

Input
{"a":1,"b":2} against {"b":2,"a":1}
Result
No differences — the two objects are identical

A text diff reports two changed lines here.

A number that became a string

Input
{"retries":3} against {"retries":"3"}
Result
Type changed at $.retries — number to string

About the json diff

What a path tells you

Each row is labelled with a JSONPath-style location such as $.users[2].email. That is not decoration: it is a string you can paste into a query tool, a log search or a jq expression to look at the value in context.

Keys that are not plain identifiers get bracket notation with quotes, so a key containing a dot or a space still produces a path you can use rather than one that silently means something else.

Comparing API responses over time

The common use for this is checking whether an upstream service changed its output. Recording a response, coming back after a deployment, and diffing the two answers the question directly — and it answers a second one that a text diff cannot, which is whether the change is cosmetic.

Serialisers reorder keys between library versions, change their indentation, and alter how they escape non-ASCII characters, all without changing a single value. A structural comparison filters that noise out, which means a non-empty result is worth investigating rather than worth scrolling past.

Frequently asked questions

Why does reordering keys report nothing?
Because an object is an unordered collection of name-value pairs, by the JSON specification and by every parser that implements it. Two objects with the same pairs in a different sequence are the same object, so reporting a difference there would be reporting a difference in how the file was written rather than in what it means.
Which array comparison should I choose?
By position, if the order carries meaning — a tuple, an ordered log, a sequence of steps. As a set, if it does not — a list of records that came back from a query with no ORDER BY. The trade-off is visible in both directions: comparing by position reports every element after an insertion as changed, and comparing as a set reports a genuine reordering as no change at all.
What is a type change and why is it listed separately?
It is a value whose JSON type differs between the two sides — a number against a string, an object against an array, something against null. They get their own category because they are the changes most likely to break whatever consumes the document, and because they are nearly invisible in a text diff: one pair of quotation marks separates a working numeric comparison from a silent failure.
Is anything I paste sent to a server?
No. Both documents are parsed and compared by JavaScript in your own browser, which is worth knowing given how often the two things being compared are production API responses.