What is a JSON diff?
A JSON diff compares two JSON documents by the data they hold rather than by their text. This tool reads both with a strict parser and lists every value that was added, removed, or changed, each with its JSONPath, such as $.config.theme or $.users[1].role. Key order and formatting don't count, numbers are compared exactly, and items inserted into or removed from an array are found as such. It updates as you type and runs in your browser.
Comparing JSON by its data, not its text
A text diff of two JSON documents reports every change of indentation, spacing, or key order, even when the data is the same. JSON Diff reads both documents and compares what they hold: objects by member name in any order, strings by the text they stand for ("\u0041" and "A" are the same), and numbers by their value (1, 1.0, and 1e0 are the same number). What's left is only the data that changed.
Numbers are compared exactly, as written, not as JavaScript reads them: 12345678901234567890 and 12345678901234567891 are different numbers, although JSON.parse turns both into 12345678901234567000. The tool also warns about such numbers, and about duplicate keys, where like most parsers it compares the last value.
How differences are listed
Each difference is one line: + for a value that was added, - for one that was removed, and ~ for one that changed, then its JSONPath and the value (old → new for a change). Paths use the dot form, $.config.theme, where JSONPath (RFC 9535) allows it: for names made of ASCII letters, digits, _, and characters beyond ASCII that don't start with a digit. Any other name uses the bracket form, $['a.b'], so every path names exactly one place. Values are written as compact JSON, in full, with numbers and strings exactly as they appear in the document.
A change deep inside an object or array is reported at the deepest place that changed, so editing one field of one user in a list gives one line, such as ~ $.users[1].role: "user" → "admin". A value whose type changes, such as null becoming an object, is one change at that path.
How arrays are compared
Array order matters in JSON, so arrays are compared item by item in order, but items that were inserted or removed don't shift everything after them: the tool keeps as many items in place as possible (a longest common subsequence of the two arrays) and reports only the rest. Inserting "yaml" into ["json", "base64"] gives one line, + $[1]: "yaml". Between the items kept in place, an original and a modified item at the same position are compared member by member, so a changed object in a list shows the field that changed.
Paths in the modified document use its positions; a removed item's own position is the one it had in the original. A moved item shows as removed at its old position and added at its new one, or as a change where another item took its place. For two very long arrays with many repeated values and many differences, where finding the fewest changes would take too long, the items that couldn't be matched quickly are compared by position.
Errors, warnings, and sharing
If either document isn't valid JSON, the tool shows which one, the line and column, and what's wrong, such as "Original JSON, line 1, column 7: Trailing commas aren't allowed in JSON", and Go to error moves the cursor there. Copy output copies the list of differences, and Share link creates a link that reopens both documents.
How to compare two JSON documents
- 1Paste both documents. Paste the original JSON on the left and the modified JSON on the right, or load the sample.
- 2Read the differences. The list updates as you type: + added, - removed, and ~ changed, each with its JSONPath. If a document isn't valid JSON, the error shows which one and where.
- 3Swap or share. Swap sides compares in the other direction. Copy output copies the list, and Share link creates a link to both documents.
Examples
A changed value
Input
Original: {"active":true}
Modified: {"active":false}Output
~ $.active: true → false
An added key
Input
Original: {"id":1}
Modified: {"id":1,"name":"Ada"}Output
+ $.name: "Ada"
Key order and number format don't count
Input
Original: {"a":1,"b":2}
Modified: {"b":2,"a":1.0}Output
No differences.
An item inserted into an array
The items after it aren't reported as changed.
Input
Original: ["json","base64","regex"] Modified: ["json","yaml","base64","regex"]
Output
+ $[1]: "yaml"
A field changed inside an array of objects
Input
Original: {"users":[{"id":1,"role":"user"},{"id":2,"role":"user"}]}
Modified: {"users":[{"id":1,"role":"user"},{"id":2,"role":"admin"}]}Output
~ $.users[1].role: "user" → "admin"
Large numbers compared exactly
JSON.parse reads both as 12345678901234567000; the tool also warns about that.
Input
Original: {"id":12345678901234567890}
Modified: {"id":12345678901234567891}Output
~ $.id: 12345678901234567890 → 12345678901234567891
A name that needs the bracket form
Input
Original: {"a.b":1,"tags":["x"]}
Modified: {"a.b":2}Output
~ $['a.b']: 1 → 2 - $.tags: ["x"]
Invalid JSON
No differences are listed until both documents are valid.
Input
Original: {"a":1,}
Modified: {"a":1}Output
Original JSON, line 1, column 7: Trailing commas aren't allowed in JSON: remove this comma.
Reading the differences
Each line is one difference, with its JSONPath.
| Line | Meaning |
|---|---|
| + $.name: "Ada" | Added: the value is only in the modified document |
| - $.author: "DevTeam" | Removed: the value is only in the original document |
| ~ $.version: "1.0.0" → "2.0.0" | Changed: the old value, then the new one |
| $.config.theme | A member, in the dot form |
| $['a.b'] | A member whose name needs the bracket form |
| $.tools[1] | An array item, counted from 0 |
| No differences. | Both documents hold the same data |
Frequently asked questions
How is this different from a text diff?
A text diff compares lines of text, so a different key order, indentation, or number format shows as a change. JSON Diff compares the data: objects by member name in any order, strings by the text they stand for, and numbers by value, so it lists only real changes, each with its JSONPath. For a line-by-line comparison of any text, use the Diff Checker.
Does key order matter?
No. Objects are compared by member name, so the same members in a different order aren't a difference.
Does array order matter?
Yes, because it does in JSON. Arrays are compared in order, keeping as many items in place as possible, so an inserted or removed item is reported once instead of shifting every item after it. An item that moved shows as removed at its old position and added at its new one, or as a change where another item took its place.
Are numbers compared exactly?
Yes. Numbers are compared by their exact value as written, so 12345678901234567890 and 12345678901234567891 differ, although JavaScript's JSON.parse reads both as the same number. Different ways of writing the same number, such as 1, 1.0, and 1e0, or 0 and -0, are equal.
What does a path like $['a.b'] mean?
Paths are JSONPath (RFC 9535). The dot form, $.config.theme, is used for names made of ASCII letters, digits, _, and characters beyond ASCII that don't start with a digit; any other name, such as one with a dot, a space, or nothing at all, uses the bracket form, $['a.b'], so every path names exactly one place. Array items are counted from 0.
What if a document isn't valid JSON or has duplicate keys?
The tool shows which document has the problem, the line and column, and what's wrong, and Go to error moves the cursor there; differences are listed once both are valid. A duplicate key gets a warning, and like most parsers the tool compares its last value.
Can I copy or share the result?
Copy output copies the list of differences, in full. Share link creates a link that reopens both documents, so the comparison can be seen and changed again.
Is my data private?
Yes. Both documents are compared in your browser and aren't uploaded. The only exception is the Share link button, which uploads both documents when you click it, so the link can reopen them.
Is it free?
Yes — free and unlimited.