Compare two JSON files by parsing both documents as data, walking them recursively, and reporting a deterministic list of added, removed, changed, and type-changed entries at RFC 6901 JSON Pointer paths. A purely textual diff between two JSON files produces noise: reformatting, key sorting, or stray whitespace shows up as changes that do not actually change the data. The structural approach used by the JSON Diff tool parses both sides as strict RFC 8259 JSON, compares objects by their own member names without depending on source order, and compares arrays by zero-based position. The output is a review list with each difference tagged at a precise JSON Pointer path, the same path syntax that drives JSON Patch and other standards, together with the left value, the right value, or both. That gives you one source of truth for where the documents disagree, whether the disagreement is a value change, a type change, or an entirely new or missing branch.

What Structural JSON Comparison Actually Means
A textual diff between two JSON files shows every byte that changed, which is rarely what you want. Two semantically identical JSON values can differ on disk in dozens of places: pretty-printed versus compact, keys in different orders, tabs instead of spaces, a trailing newline, numbers written as 1 versus 1.0. None of that is a meaningful difference to the consumer of the data, and yet every byte-level diff flags each one as a change.
Structural comparison parses both documents as JSON first and walks the resulting object graph. Whitespace and member order stop being part of the input. The comparison itself becomes a recursive walk that classifies every observed difference as one of four kinds: added, removed, changed, or type-changed. Each entry carries the RFC 6901 JSON Pointer path where the difference was found and the left and/or right values involved. JSON Pointer is the path syntax defined in RFC 6901, which sits on top of RFC 8259-compliant JSON, so the change list reads the same way a JSON Patch document reads. For a text-only side-by-side workflow in your editor, the Diff Checker is the right companion — see the VS Code text-diff browser workflow guide for the contrast. For a data-level review, structural comparison is the right tool.
How to Compare Two JSON Files in Your Browser
- Prepare strict RFC 8259 JSON for both sides. If either side has trailing commas, comments, or undefined values, fix that first with a formatter such as the JSON Formatter or a validator like the JSON Validator, because strict parsing rejects those inputs outright.
- Open the JSON Diff tool and paste the left value into the left input and the right value into the right input. Formatting and object member order may differ on the two sides, and that does not create noise.
- Run the comparison and inspect the resulting list. Each row identifies a difference, the JSON Pointer path where it was observed, the previous value (left), and the new value (right) where applicable.
- Copy the change list as a review artifact into a code review, ticket, or chat thread. Treat the copied text as documentation rather than an executable operation.
- If you intend to apply the changes automatically, write tests around a maintained patch library and a deterministic JSON parser; the change list itself is not a runnable patch, and its paths describe observed locations, not guaranteed operations.
How Each Difference Is Classified at a JSON Pointer Path
Every entry in the result is one of four kinds, with the same fields reported in each case. The root of the document is the empty JSON Pointer; when the two values differ at the very top, the tool displays that as root in the human-readable list.
| Kind | Path contains | Left value | Right value |
|---|---|---|---|
| Added | JSON Pointer where the value appears | — (none) | the new right-side value |
| Removed | JSON Pointer where the value was | the old left-side value | — (none) |
| Changed | JSON Pointer to the position | previous value of the same JSON type | new value of the same JSON type |
| Type-changed | JSON Pointer to the position | old value with its original type | new value with its new type |
Object and array subtrees can appear as a value when a whole member is added, removed, or has its type change, so the report is not limited to primitives. JSON Pointer escaping is RFC 6901 compliant: a literal slash inside a member name becomes ~1 and a literal tilde becomes ~0, while array positions use decimal index tokens. If you copy a path into another tool, keep that escaping intact, or the path will silently refer to the wrong location.
Why Object Order Is Ignored and Array Order Is Not
JSON objects are unordered collections of name/value pairs and the comparison reflects that. It walks the own enumerable members of each side, sorts the keys for deterministic reporting, and compares values by their member names. A key present only on the right becomes an added entry; a key present only on the left becomes a removed entry; a key on both sides is compared recursively. Reordering keys in the source text is not a difference at all, because the parsed object mapping is identical. Duplicate names in the raw JSON text cannot be compared as separate entries, because the strict JSON parser has already collapsed them into one mapping before the comparison sees the value.
JSON arrays are ordered sequences and are compared by zero-based position. If a value moves from index 2 to index 5, the result contains a removal at index 2, an addition at index 5, and several changed or type-changed entries where the displaced elements now sit, not a single semantic move. The tool does not guess identity keys, compute a longest common subsequence, or treat arrays as sets; those policies depend on the data contract and can hide meaningful ordering changes that the consumer cares about.
Limits, Rejections, and When to Reach for Another Tool
Strict RFC 8259 parsing means that comments, trailing commas, undefined, NaN, Infinity, BigInt syntax, and JavaScript object literals are rejected. If your inputs come from a relaxed dialect, run them through a JSON5-aware normalizer first; otherwise the comparison will not start at all.
Each side can be any JSON value: object, array, string, number, Boolean, or null. The limits you must respect for the comparison to complete are:
- up to 500,000 characters per input;
- up to 50 comparison levels of nesting;
- up to 5,000 differences in the result.
If a result would exceed 5,000 differences, the tool fails rather than truncating. That is by design, because a truncated change list can drive an automated patch application to a different document than you intended. Plan to narrow the inputs, fix the data shape, or compare region by region when you approach these ceilings.
Numbers are parsed as JavaScript Numbers, so integers outside the safe range and fine decimal distinctions may already be rounded before the comparison runs. Positive and negative zero compare as the same JSON numeric value. If your contract cares about exact decimal spelling, duplicate object names, or arbitrary-precision integers, do not rely on this browser representation. Use a parser and numeric model designed for that contract, or inspect the bit-level IEEE 754 encoding with the IEEE 754 converter before deciding whether two parsed numbers are really equal.
Reading the Change List Before Doing Anything With It
The output of JSON Diff is a product-defined change list with deterministic ordering. It is intentionally not RFC 6902 JSON Patch, JSON Merge Patch, a text unified diff, or a schema migration. There are no move, copy, or test operations, and a removed value cannot be assumed to be restorable after surrounding changes have been reported. Treat the list as a structured review artifact: copy it into a pull request description, attach it to a bug, or share it with a teammate before deciding what to do.
When automated application is appropriate, reach for a maintained patch implementation that targets your data store or document and pair it with application-specific tests. Eight external fixtures cover the standard cases: changed, added, removed, type-changed, array index, slash escaping, tilde escaping, and object-order equality. Additional tests cover deterministic nested changes and signed zero, so the comparison itself is well behaved, but the gap between "the comparison reports where" and "applying this creates the document I wanted" is real. Always review sensitive before-and-after values before copying the change list into a place that persists, such as a chat channel or a ticket body.
Related reading: Format JSON in IntelliJ IDEA: Shortcuts and Browser.