Just File Tools

How to compare two JSON files semantically (not just as text)

A text diff treats reordered keys as changed. A JSON diff understands structure. Use the right tool to spot the actual differences.

Uses tool: JSON Diff

Comparing two JSON documents seems like a job for a text diff. Just run diff a.json b.json and read the result. The problem with that approach: a text diff treats JSON as character sequences. Reorder the keys in an object and a text diff says "this changed". Add or remove whitespace and a text diff says "this changed". Both are textually different but semantically identical (JSON objects are unordered; whitespace is insignificant). For API response debugging, configuration comparison, or any task where "what actually changed" matters, a JSON-aware diff is the right tool.

Text diff vs JSON diff

Consider these two documents:

// a.json
{ "name": "Alice", "age": 30, "city": "NYC" }

// b.json
{
  "city": "NYC",
  "age": 30,
  "name": "Alice"
}

A text diff reports every line as different. A JSON diff reports zero changes — both documents represent the same object. JSON objects don't have ordered keys (per RFC 8259), and most JSON consumers (parsers, serializers, schema validators) treat them as unordered. The text-diff result is technically correct but practically useless; the JSON-diff result is what you actually want.

Conversely, consider:

// a.json
{ "items": [1, 2, 3] }

// b.json
{ "items": [1, 3, 2] }

A JSON diff reports two changes: items[1] changed from 2 to 3, and items[2] changed from 3 to 2. Arrays in JSON are ordered (per the spec), so reordering an array is a semantic change. This matches every real JSON consumer's interpretation.

Step-by-step with our tool

  1. Open justfiletools.com/tools/json-diff.
  2. Paste the first JSON document into the left textarea.
  3. Paste the second JSON document into the right textarea.
  4. Click Compare. The output shows every path that differs, with the old and new values.

Each change is reported as a single line: the path (using JavaScript dot-and-bracket notation, like users[0].email), the change type (added, removed, changed), and the values involved. The change types map to:

  • added — the path exists in the new version but not the old. Shows the new value.
  • removed — the path exists in the old version but not the new. Shows the old value.
  • changed — the path exists in both but the value is different. Shows old → new.

The path notation

Paths use the syntax you'd type in JavaScript to reach a value:

  • server.host — the host property of the server object.
  • users[0].email — the email property of the first user in the users array.
  • [3].name — the name property of the fourth item in a top-level array.
  • ["user-id"] — a property name that contains characters not allowed as an identifier (dashes, spaces).
  • (root) — when the entire document changed type (object replaced by array, etc.).

Useful workflows

API response debugging. Save the response from your test environment and the response from production for the same endpoint. Paste both into the JSON Diff. The output shows exactly which fields differ, which is faster than reading both documents and trying to spot changes visually.

Configuration drift detection. Compare a Kubernetes manifest, a docker-compose file, or any structured config across environments. The diff surfaces the actual differences (port numbers, resource limits, image tags) without drowning in formatting noise.

Schema validation. Compare a JSON Schema to a sample document to spot fields you forgot to define, or to identify where the schema and the sample have drifted apart.

Database row comparison. Dump two rows of jsonb data from PostgreSQL and compare. The diff shows which fields changed in a record over time.

Common pitfalls

Type mismatches are reported as single changes. If one side has "count": 42 and the other has "count": "42", the diff reports a single "changed: number → string" entry rather than separate add/remove operations. This is the more useful interpretation.

null vs missing. { "a": null } and {} are different. The first explicitly states that a is null; the second says nothing about a. The diff reports { "a": null }{} as a removed key. Most consumer code treats them differently in practice.

Whitespace and key order are ignored. The diff parses both sides to structured values before comparing. Formatting differences disappear.

Code equivalent

The algorithm is a recursive walk of both trees in parallel. For objects: collect the set union of keys, and for each key recurse on the two sides' values (or mark added/removed if a key is in only one side). For arrays: walk by index, recurse on each position. For primitives: equality check.

Plenty of libraries implement this (jsondiffpatch, deep-diff, microdiff). Our in-browser tool uses a small custom implementation tuned for the kind of output that's useful at a glance — flat list of paths-and-changes, no nested visualization. For more elaborate visual diffs (color-highlighted side-by-side, collapsible nesting), a desktop tool like Beyond Compare or a code editor's JSON diff plugin is the right call.

Alternative approaches

  • jq + diff. diff <(jq -S . a.json) <(jq -S . b.json) normalizes both files (sorted keys, consistent formatting) and runs a text diff on the normalized versions. Works for simple cases but reports formatting differences as changes if the documents have different array element ordering on insignificant arrays.
  • VS Code's JSON diff. Open both files and use the side-by-side compare view. Visual, color-highlighted, decent for small files. Treats JSON as text (same caveat as diff).
  • jsondiffpatch. The most popular JS library for semantic JSON diffs, with a JSON Patch (RFC 6902) output mode useful for replicating changes programmatically. Heavyweight for a one-off comparison; right tool for production diff replay.
  • Postman / Insomnia. If you're comparing API responses, both have response-diff features when you save responses to history. Convenient for API debugging.

Privacy considerations

JSON files you'd want to diff often contain real data — production API responses with user emails, configs with secrets, log entries with internal identifiers. The in-browser tool's diff runs as a JavaScript function in your tab. Both inputs are parsed with native JSON.parse and walked locally. Verify in DevTools: zero network requests during the diff.

Related tools and guides

Try it now: JSON Diff

Structural diff of two JSON documents — added, removed, and changed paths

Open JSON Diff