JSON Diff: Compare Two JSON Files Online
Paste, format, and compare two JSON snippets side-by-side. Validation, pretty-print, and minify built in.
A free, in-browser tool for comparing two JSON documents. Paste an old version on the left, the new one on the right, and the differences light up character by character. Nothing leaves your machine.
Underneath, it uses Google's diff-match-patch for the diff itself, and your browser's native JSON.parse for validation. There's a Format button when your JSON is one giant minified line, a Minify button for the opposite case, and live validation that flags syntax errors as you type.
If you've ever stared at a 6,000-line openapi.json diff in a GitHub PR and tried to find the one field that broke a downstream client, this is the tool that gets you there in seconds.
How the diff actually works
The diff is character-level using diff-match-patch, then cleaned up with semantic post-processing so the highlights land on meaningful chunks rather than random characters. Insertions show in green on the right pane, deletions in red on the left.
JSON has its own quirks the spec calls out. The JSON specification in RFC 8259 defines objects as unordered, so reordering keys is technically a no-op even though a text diff will flag it. We handle that by giving you a Format button on each side: format both, then compare, and the order is consistent. For deeper structural work, take a look at JSON Patch (RFC 6902) or the simpler JSON Merge Patch format (RFC 7396), which are the two standard ways to describe a JSON change as data.
When ordering matters for hashing or signing, RFC 8785 (JSON Canonicalization Scheme) is the relevant spec. Sort keys, normalise number formatting, then diff.
How to compare JSON in three steps
Two text panes, one diff. There is no signup, no upload, no server round-trip.
- 1
Paste or upload your JSON
Paste the old JSON on the left, the new JSON on the right. Or click Upload on either side to load a .json file directly. The Sample button fills both panes with a small example if you want to see the tool in action first.
- 2
Format both sides for a fair comparison
Click Format on each pane to pretty-print with two-space indentation. This normalises whitespace and line breaks so the diff highlights actual data changes, not formatting differences. The validation badge turns green when your JSON parses cleanly.
- 3
Read the diff
Deletions appear with a red highlight on the left, insertions with a green highlight on the right. Scroll either side and the other follows. The change counts in each header tell you how many distinct edits the diff found.
When JSON diff is the right tool
Auditing IAM policy changes before apply
Paste the current aws iam get-policy-version output against the proposed JSON to see exactly which Action entries were added, or whether someone slipped "Resource": "*" into a previously specific statement. The AWS console reorders statements on save, which makes a GitHub diff misleading; format both sides here and the real change is obvious.
Spotting silent Terraform plan drift
When terraform show -json tfplan returns a 4 MB blob, eyeballing it is hopeless. Diff today's plan against yesterday's to surface the aws_security_group_rule someone added under a refactor PR or the lifecycle.ignore_changes block that quietly disappeared.
Reviewing OpenAPI schema changes pre-merge
A 6,000-line openapi.json diff is unreadable when a code generator reorders paths alphabetically. Format both sides, compare, and the actual change surfaces: a required field added to CreateOrderRequest, or a 200 response whose schema quietly switched from string to string | null.
Debugging package-lock.json after a merge
After resolving a package-lock.json conflict, diff your resolved file against main's lockfile to catch a transitive downgrade. npm sometimes resolves the same semver range to different exact versions across machines, which is the actual cause of "works on my machine, fails in CI". Read the package-lock.json docs for what each field means.
Comparing Elasticsearch mappings across environments
Pull GET /my-index/_mapping from staging and prod, drop both into the diff. Prod might still have "type": "text" on a field that staging migrated to "keyword" last sprint, which is why the aggregation query returns nothing in prod and works locally. Mappings nest five or six levels deep and a text diff buries this in noise.
Reproducing flaky API mocks
When a Playwright test passes locally and fails in CI, capture the JSON response body the test actually saw and diff it against the fixture in your repo. Often it's a createdAt timestamp or a traceId field that nobody pinned, and the structural diff makes the offending key obvious instead of dumping you into a wall of formatted text.
JSON quick reference
A short cheat sheet for the parsing edge cases this tool surfaces most often. All of it is grounded in the JSON specification.
| Topic | What this tool does |
|---|
| Object key order | Unordered per the spec. {"a":1,"b":2} equals {"b":2,"a":1}. Use Sort keys to normalise before diffing. |
|---|
| Array order | Ordered. [1,2,3] is not equal to [3,2,1]. Sort manually if order does not matter for your use case. |
|---|
| Trailing commas | Not allowed. { "a": 1, } is a parse error in standard JSON. Allowed in JSON5/JSONC, which are supersets — strip them first. |
|---|
| Comments | Not allowed. // like this is a parse error. JSON5 and JSONC accept them; this tool follows the strict RFC 8259 grammar. |
|---|
| Numbers | Parsed as 64-bit IEEE 754 floats. 0.1 + 0.2 = 0.30000000000000004. Integers above 2^53 − 1 lose precision; store snowflake IDs as strings. |
|---|
| Duplicate keys | The spec calls them undefined behaviour. Most parsers keep the last occurrence. The diff will show all of them, which is usually what you want when auditing config files. |
|---|
| Encoding | UTF-8 only. RFC 8259 forbids a UTF-8 BOM at the start of the document; some parsers accept it anyway, but the spec does not. |
|---|
| Null vs missing | A key with value null is present. A missing key is absent. Different from JavaScript's undefined, which has no JSON representation. |
|---|
JSON diff: frequently asked questions
Does this save or upload my JSON anywhere?
No. The diff runs entirely in your browser. Nothing is sent to a server, logged, or stored. Paste an internal API response or an IAM policy and close the tab; there is no copy left behind. To verify, open DevTools, switch to the Network tab, and watch — there are no outbound requests when you compare.
How is JSON diff different from a regular text diff?
A text diff compares characters line by line, so reformatting, key reordering, or whitespace changes show up as differences even when the data is identical. Click the Format button on both panes to pretty-print first, and the diff focuses on real data changes. For a fully structural compare that ignores key order, sort the keys on both sides before diffing.
Does the order of keys in a JSON object matter?
For object keys, no — the JSON spec says objects are unordered, so {"a":1,"b":2} and {"b":2,"a":1} represent the same data. A character diff will still flag the reorder, which is why the Format button matters. Arrays are different: [1,2,3] and [3,2,1] are not equal because array order is meaningful in JSON.
Why does 0.1 + 0.2 not equal 0.3 in my diff?
Because IEEE 754 floating-point. 0.1 + 0.2 is actually 0.30000000000000004, and JSON.parse reads numbers as 64-bit floats. Big integers hit the same limit: anything past 2^53 - 1 (9007199254740991) loses precision, so a Twitter-style snowflake ID won't round-trip. If precision matters, store those as strings.
Can I paste JSON with comments or trailing commas?
Standard JSON does not allow either. { "a": 1, } or // comment will give you a parse error. That's JSON5 or JSONC (the format VS Code uses for settings.json), which is a superset. Strip the comments and trailing commas first. We follow the strict RFC 8259 grammar on purpose so the diff matches what your API actually accepts.
How big a JSON file can I diff before it gets slow?
Up to a few MB is fine, sub-second. Past 10 MB the browser starts to feel it, mostly because rendering the diff (not computing it) is what gets expensive. For 50 MB+ exports, filter both sides to the subtree you care about with jq first, then paste that.
Privacy and how this works
Your JSON never leaves your browser. The parser, formatter, and diff all run on your machine, locally. No analytics on your input, no logs, no "helpful" cloud round-trip. The whole tool is open about its dependencies: parsing uses the browser's native JSON.parse, the diff is Google's diff-match-patch (Apache 2.0), and the JSON spec we follow is RFC 8259.