Skip to content

JSON Diff & Compare

Compare two JSON documents structurally, so reformatting and key order are ignored and only real changes are reported — with a JSON Patch export.

Original

Changed

Changes

Paste valid JSON into both panes to compare them.

Both documents are parsed and compared in your browser — nothing is uploaded. Because the comparison is structural, reindenting a file or reordering its object keys produces no changes at all.

About the JSON Diff & Compare

Compare two JSON documents and see only what actually changed. This is a structural diff, not a text diff: both sides are parsed first, then compared value by value, so indentation, line endings and object key order are invisible to it. Two files that a text diff reports as completely different can be identical here — and that is the correct answer, because none of those things is meaningful in JSON.

Every change is reported at its own path. `$.plan.tier` changed from "pro" to "enterprise" reads as one change, at one place, whatever the surrounding formatting looks like. Changes are classified as added, removed, changed, or a type change — a field going from a number to a string is called out separately, because that is the one that breaks a consumer at runtime rather than merely surprising a reviewer.

Arrays are compared by index by default, since order in a JSON array is data. There is one refinement: when both sides are arrays of objects sharing an obvious identity field — `id`, `_id`, `uuid`, `key`, `name` or `slug` — elements are paired on that field instead. Inserting one record at the front of a list of a hundred then reports one addition rather than a hundred modifications.

  • Structural comparison: formatting and key order are ignored, because JSON does not define them
  • Every change located by path, e.g. $.plan.seats or $.items[2].sku
  • Type changes reported separately from value changes
  • Arrays of records matched on their id, so an insertion is one change
  • Optional unordered array comparison, and case-insensitive string comparison
  • Export as an RFC 6902 JSON Patch you can apply programmatically

How to use it

  1. Paste the original document on the left and the changed one on the right.
  2. Read the change list. Each row shows the kind of change, the path it happened at, and the values on either side.
  3. Turn on Ignore array order if the two lists hold the same items in a different order and that difference does not matter to you.
  4. Switch to Patch to get the same diff as an RFC 6902 JSON Patch — the format `jsonpatch` libraries apply.
  5. Copy either view.

Real-world use cases

Backend & API developers

Compare an API response before and after a deploy to see exactly which fields changed, without formatting or key-order differences drowning out the one field that actually matters.

QA & test engineers

Diff an expected fixture against an actual response in a failing test, getting a path-level answer — $.items[2].price changed — instead of re-reading two walls of JSON by eye.

DevOps & platform engineers

Compare two versions of a Kubernetes ConfigMap or a Terraform plan's JSON output to confirm a change only touched the field it was supposed to.

API product & platform teams

Check two versions of a public response schema for type changes specifically — a field moving from number to string is the class of change that silently breaks a consumer.

Support & debugging engineers

Paste a customer's "it used to work" payload against a known-good one to isolate the actual difference in seconds, in a browser tab that never sends the data anywhere.

Examples

Reordered keys are not a change

Input
{"id": 1, "name": "Ada"}
{"name": "Ada", "id": 1}
Output
No changes

JSON object members are unordered by specification. A text diff calls this a rewrite of both lines; a structural diff calls it nothing, which is what you wanted to know.

A value change and a type change are different

Input
{"seats": 3, "active": true}
{"seats": "3", "active": false}
Output
type     $.seats    number → string
changed  $.active   true → false

`3` becoming `"3"` is the change that breaks the consumer doing arithmetic on it. Reporting it as its own kind is the point of parsing rather than diffing text.

An insertion into a list of records

Input
[{"id": "a"}, {"id": "b"}]
[{"id": "c"}, {"id": "a"}, {"id": "b"}]
Output
added  $[0]  {"id":"c"}

Both sides have a unique `id`, so elements are paired on it. Without that, index-by-index comparison would report all three positions as changed.

As a JSON Patch

Input
{"a": 1, "b": 2}
{"a": 9, "c": 3}
Output
[
  { "op": "replace", "path": "/a", "value": 9 },
  { "op": "remove", "path": "/b" },
  { "op": "add", "path": "/c", "value": 3 }
]

Patch paths are JSON Pointers, which escape `/` as `~1` and `~` as `~0`. That is a different escaping scheme from the display paths in the list view.

Common errors

MessageCauseFix
Everything is reported as changedThe two documents are arrays whose elements shifted by one, and the elements have no shared identity field to pair on.If order does not matter, turn on Ignore array order. If it does, this is the honest answer: index 2 really does hold a different value now.
A change I can see is not listedIt is a formatting difference — indentation, trailing newline, key order, or `1.0` versus `1`, which parse to the same number.Nothing to fix. If you need to compare bytes rather than values, use the text diff checker instead.
Unexpected token in JSONOne side is not valid JSON — most often a trailing comma, single quotes, or a JavaScript object literal pasted in place of JSON.The pane reports the line and column. Format the document first if you need to find it in a large file.
Large numbers appear to change when nothing didJSON numbers are IEEE 754 doubles. An integer beyond 2^53 loses precision when parsed, on both sides, and can round to different values.Send such identifiers as strings. This is a property of the format, and affects every JSON parser equally.
The diff is slow on a huge documentUnordered array comparison is quadratic: every element on the left is compared against the unused elements on the right.Leave Ignore array order off for large arrays, or compare the specific subtree you care about.

Frequently asked questions

Are my documents uploaded anywhere?

No. Parsing and comparison both happen in your browser. API responses, tokens and customer records in the payload never leave the page, and nothing is stored or logged.

Why does a JSON diff ignore key order when git does not?

Because JSON objects are unordered by specification: `{"a":1,"b":2}` and `{"b":2,"a":1}` are the same value, and any parser will produce identical results from them. Git compares bytes, so it has no choice but to report a reordering as a change. Comparing parsed values removes that entire class of false positives — which is the reason to use a JSON diff rather than a text diff.

Does it ignore array order too?

Not by default, because order in an array is data — `[1,2]` and `[2,1]` are genuinely different values. You can turn on Ignore array order when your list is really a set. Arrays of objects with a unique id are always paired on that id, which handles the common case of an inserted or moved record without changing the semantics of ordinary arrays.

What is a JSON Patch, and when would I use one?

RFC 6902 defines a JSON document that describes how to transform one JSON value into another: a list of add, remove and replace operations addressed by JSON Pointer. It is what you send to an API that accepts PATCH with `application/json-patch+json`, and it is a compact way to store or replay a change. Every mainstream language has a library that applies one.

How do the two path formats differ?

The change list uses JSONPath-style display paths — `$.plan.seats`, `$.items[2]` — because they are what you would type to reach the value in code. The patch view uses JSON Pointer, which is what RFC 6902 requires: slash-separated, with `~1` for a literal `/` and `~0` for a literal `~`.

Can it compare JSON Lines, or two files with several documents?

Not directly — each pane expects a single JSON value. For JSON Lines, wrap the lines in an array on both sides first; the identity-key matching then pairs the records up for you.

How is this different from a text diff on two JSON files?

A text diff (like the one in git or a plain diff checker) compares lines and characters, so reformatting, re-indenting or reordering keys shows up as a change even when the underlying value is identical. This tool parses both sides first and compares the resulting values, so only real differences — the ones that would matter to code consuming the data — are reported.

What counts as a shared identity field for matching array elements?

id, _id, uuid, key, name and slug — checked in that order, on both sides, only when every element in the array has one and the values are unique. If no field qualifies, elements are compared by index instead, which is the correct behaviour for arrays that are genuinely ordered lists rather than unordered collections of records.

Last updated