A JSON diff viewer answers a question a plain text diff cannot: what actually changed in this document, as opposed to what merely moved. JSON objects have no defined key order — {"a":1,"b":2} and {"b":2,"a":1} are the same object to every parser on earth — yet a line-based diff will paint both lines red and green and leave you to work out that nothing happened. This tool parses both sides into real data structures, walks them by key path, and reports only the differences that would change how a program behaves.
Arb Digital's engineering team built this because config drift between environments is one of the most common causes of "it works on staging" incidents, and the usual way of investigating it — pasting two config dumps into a text differ — produces so much noise that the one meaningful change gets lost. Everything here runs in your browser. No JSON is transmitted anywhere, which matters when the document you are comparing is a production config.
What This JSON Diff Viewer Does
Paste two JSON documents. The tool parses each one, then recursively compares them node by node, building a dotted key path for every point of difference: env.LOG_LEVEL, features[2], replicas. Each difference is classified into one of four categories — added, removed, changed, or type-changed — and the four counters above the report give you the shape of the change set at a glance before you read a single line.
The headline number is the total count of structural differences. If it reads zero, the two documents are semantically identical even if the raw text differs in key order, indentation, or whitespace. That single fact is often the entire answer you needed.
Arrays are handled two ways because arrays mean two different things in practice. An ordered array — a sequence of pipeline steps, a list of middleware — must be compared by index, since moving an element changes behaviour. An unordered array — a set of feature flags, roles, or tags — should be compared as a set, where adding "metrics" at the end is one addition rather than a cascade of index shifts. Switch modes with the array comparison dropdown and watch the difference count change.
How to Use It
- Paste the baseline document on the left. This is your "before": the version in production, the committed fixture, the config you know works.
- Paste the changed document on the right. The one you are proposing, or the one an environment is actually running.
- Choose an array comparison mode. Index mode for ordered sequences, set mode for tag-style lists where order carries no meaning.
- Click Compare JSON. The hero shows the total difference count, the grid breaks it down by category, and the report lists every path with its old and new value.
- Copy the report into a pull request comment, an incident ticket, or a change record. It is plain text and reads cleanly in a monospace context.
How the Comparison Is Calculated
Both inputs are parsed with the browser's native JSON.parse, so anything that is not valid JSON fails immediately and is reported as a parse error rather than silently producing a misleading diff. The behaviour of that parser, including how it handles duplicate keys by keeping the last occurrence, is documented in MDN's reference for JSON.parse, and it is worth knowing about because a document with repeated keys will quietly lose data before the comparison even begins. If you need to fix malformed input first, our JSON validator points at the exact character position of the syntax error, and the JSON formatter will pretty-print a minified blob so you can read it.
Once both sides parse, the algorithm walks them together. At each node it compares types first. If the types differ — object versus array, number versus string, anything versus null — that is recorded as a type change and the walk does not descend further, because there is no meaningful correspondence between the children of a number and the children of an object. If both sides are objects, it takes the union of their keys: keys only on the left are removals, keys only on the right are additions, and shared keys are compared recursively. If both sides are arrays, it either compares element by element up to the longer length (index mode) or compares the two as multisets of serialised elements (set mode). If both sides are scalars, it compares them strictly, so 1 and "1" are never treated as equal.
That strictness is deliberate. JavaScript's loose equality would call 0 and "" and false interchangeable in some comparisons, which is exactly the class of bug a config diff is supposed to surface, not hide.
How This Differs From a Plain Text Diff Checker
This is the boundary worth being explicit about: our diff checker compares any two blocks of text line by line and is the right tool for prose, source code, logs, CSVs, and anything where line position is itself meaningful. This page compares two JSON documents as data structures, so key order, indentation, trailing commas in your editor, and line wrapping are all invisible to it. Use the text diff checker when you care about the file; use this when you care about the object the file represents.
The practical consequence shows up the first time someone runs a formatter over a config file. A text diff of that commit is a wall of changes. A structural diff of the same commit reports zero differences, which tells you instantly and with certainty that the reformat was safe. Going the other way, a text diff can miss a real change hiding inside a single long minified line, while the structural diff pins it to an exact key path.
Why Type Changes Get Their Own Counter
Of all the ways a JSON document can change, a silent type change is the one most likely to reach production and cause an outage. A port defined as the number 8080 and a port defined as the string "8080" look nearly identical in a rendered diff, especially at a glance in a review, but they behave differently the moment something does arithmetic, a strict comparison, or a schema validation on that field. The same applies to a boolean written as "false", a numeric ID that becomes a string after a database migration, and an empty array that becomes null.
Those last two are worth dwelling on. Many serialisation layers convert an empty collection to null, and many consumers then crash trying to iterate it. Because null is its own type in JSON, this tool flags [] → null as a type change rather than a value change, which is the classification that matches how it will actually fail. If your consumers rely on the JSON data interchange format defined in RFC 8259, six types exist — object, array, string, number, boolean, and null — and a transition between any two of them is a contract change, not a cosmetic one.
Comparing API Responses Between Versions
The most useful non-obvious application is regression-checking an API. Capture a response from the current version of an endpoint, capture the same response from a release candidate, and diff them. Additions are usually safe: a new field appearing in a response rarely breaks a well-written client. Removals and type changes are the ones that break contracts, and separating them into their own counters means you can judge the risk of a release in about three seconds rather than reading the whole payload.
One caveat that trips people up: responses containing timestamps, request IDs, signed URLs, or randomised ordering will produce differences on every single run, because those values are supposed to change. Either strip those fields before comparing, or read past them in the report. If you are automating this comparison in a test suite, the standard practice is to normalise volatile fields to a fixed placeholder before the diff runs.
Nested Objects and the Key Path Notation
Every difference is reported at a full path from the document root, using dot notation for object keys and bracket notation for array indices — env.TIMEOUT, services[0].image, rules[3].match.headers[1]. This is the same shape of path used by JSONPath expressions and by most schema validators when they report errors, so a path from this report can usually be pasted straight into another tool or into a search across your codebase to find where that field is read.
Paths also make the report machine-readable enough to be useful in review comments. "The config changed" starts an argument. "env.LOG_LEVEL changed from info to debug and port changed type from number to string" ends one. When you need the same rigour on a different serialisation format, our JSON to YAML converter and YAML to JSON converter let you normalise both sides into JSON first and then compare here.
Set Mode, Duplicates, and Why It Matters
Set mode compares arrays as multisets: it counts how many times each serialised element appears on each side and reports the surplus. This means a duplicate is still detected. If the left side has ["read","write"] and the right has ["read","write","write"], set mode reports one addition rather than declaring the arrays equivalent because they contain the same distinct values.
That behaviour is intentional, because duplicated entries in permission lists and middleware chains are a real and reasonably common bug — usually the result of a merge that appended instead of replacing. A naive set comparison built on unique values would hide exactly that defect. If you genuinely want to ignore duplicates, deduplicate the array before pasting it in.
Working Safely With Configuration Files
Configuration documents frequently contain secrets: API keys, database passwords, tokens, connection strings. Everything on this page executes locally in your browser using the JSON parser built into the browser itself — nothing is sent to a server, nothing is logged, and closing the tab discards it. That said, the safest habit with any browser tool is still to redact credential values before pasting, since a browser tab can be screen-shared, screenshotted, or restored by session recovery. If your configuration lives in a .env file rather than JSON, our env file parser converts it to JSON locally and flags which values look like secrets.
Arb Digital builds and maintains web applications with proper environment parity, reviewed configuration changes, and deployment pipelines that fail loudly instead of failing quietly.
Web Development Services Talk To Our TeamCommon Mistakes to Avoid
- Diffing minified JSON in a text tool — an entire document on one line produces a single useless "line changed" result. Parse it structurally, or format it first.
- Using index mode for unordered lists — inserting one element at the start of a tag array makes every subsequent index look changed, inflating the count enormously.
- Ignoring type changes because the rendered value looks the same —
"true"andtrueprint almost identically and behave completely differently. - Comparing responses that contain timestamps or request IDs without normalising them first, then concluding the API changed when only the clock did.
- Assuming zero differences means the files are identical — it means the parsed data is equivalent. Comments, key order, and formatting are outside JSON's data model entirely.
Related Free Tools From Arb Digital
Fix malformed input with the JSON validator, make a minified document readable with the JSON formatter, compare arbitrary text line by line with the diff checker, flatten records for a spreadsheet with JSON to CSV, or move between serialisation formats with JSON to YAML and XML to JSON. The full free online tools hub lists every developer utility we publish.
Frequently Asked Questions
No. The comparison runs entirely in your browser using the native JSON parser. Nothing is uploaded, stored, or logged, and closing the tab discards everything you pasted.
Because JSON has no defined key order and no significant whitespace. If the only differences are key ordering, indentation, or line breaks, the two documents represent the same data and a structural diff correctly reports no change.
The diff checker compares any two blocks of text line by line and is right for code, prose, and logs. This tool parses JSON into data structures and compares by key path, so formatting and key order are ignored entirely.
A type change is when the JSON type itself differs between the two sides — number to string, array to null, object to boolean. These are separated because they break consumers far more often than a simple change of value.
Use index mode when position is meaningful, such as an ordered pipeline or middleware chain. Use set mode for unordered collections like tags, roles, or feature flags, where an element added at the end is one change rather than many.
It handles documents up to a few megabytes comfortably. Very large files may take a few seconds to parse and compare because the whole structure is held in memory, which is a limit of the browser rather than the algorithm.
Yes. Set mode compares arrays as multisets, so an element that appears twice on one side and once on the other is reported as an addition rather than being silently treated as equivalent.