JSON Diff Comparator
Compare JSON as parsed structures with configurable array matching and ignored paths, then review exact changes through path and patch evidence.Review decision
{{ decisionSummary }}
- {{ note }}
No policy fallback or duplicate-key warning was recorded.
| Path | Status | Original | Revised | Note | Copy |
|---|---|---|---|---|---|
{{ row.path }} | {{ row.status }} | {{ row.original }} | {{ row.revised }} | {{ row.note }} |
| Operation | Pointer | Original | Revised | Copy |
|---|---|---|---|---|
| {{ row.operation }} | {{ row.pointer }} | {{ row.original }} | {{ row.revised }} |
Two JSON documents can look different as text while representing the same structured data. Indentation and line breaks do not change a parsed value, object member order is not a dependable meaning signal, and array order may or may not matter depending on what the array represents. A useful JSON diff must therefore compare structure under explicit rules instead of comparing lines alone.
Objects are collections of named members, while arrays are ordered sequences. That distinction matters during API regression checks, configuration reviews, and data migrations. Reordering object members should normally disappear after parsing, but moving an array item can be either a real change or harmless noise. The right answer depends on whether the array is a sequence, an unordered set of primitive values, or a collection of records with stable identifiers.
| Comparison question | Useful policy | Main risk |
|---|---|---|
| Did an ordered response change? | Match array items by index. | A single insertion can shift many later paths. |
| Did an unordered scalar list change? | Count primitive values regardless of order. | Repeated values still matter because multiplicity is preserved. |
| Did records with stable IDs change? | Match array objects by a selected key. | Missing or duplicate keys force positional fallback. |
| Did a migration change only number representation? | Optionally treat numeric strings and numbers as equal. | Type differences can be hidden deliberately. |
Path-level evidence is more useful than a single changed/not-changed flag. Added values, removals, primitive edits, and type changes have different review consequences. Ignore rules can remove timestamps, request IDs, or other known noise, but every ignored path also narrows what a zero-difference result can prove.
Duplicate object names are a separate warning. JSON standards recommend unique member names because parsers do not agree on what to retain when a name repeats. A structural comparison can report the duplicate, but the parsed value may already contain only the last occurrence.
How to Use This Tool:
Choose comparison rules that match the data model before treating a path count as evidence.
- Paste or load the Original JSON and Revised JSON. Correct either parser message before reviewing differences.
- Select a Comparison profile, then confirm Array matching. Use a stable Array object key only when every record carries a unique value for that member.
- Choose the Type policy and add one exact dot path or JSON Pointer per line under Ignore paths. End a rule with
*only when the whole matching prefix should be skipped. - Check the changed-path total, then inspect removals and type changes in the Path ledger. Read any fallback, duplicate-name, or captured-row note before accepting the comparison.
Interpreting Results:
Changed paths counts added, removed, changed, and type-changed rows after the active ignore, array, and type policies. A result of zero means the documents match under those policies. It does not mean their source text is identical or that ignored values are equal.
- Review Removed and Type changed rows first because they commonly break consumers.
- When object-key matching falls back to index positions, choose a better unique key or rerun with positional matching intentionally.
- If evidence rows were truncated, narrow the documents before using the ledger as a complete audit record.
The patch rows describe add, remove, and replace-style evidence. They are not a guaranteed executable JSON Patch document, and key-based array paths may need translation for another patch system.
Technical Details:
A JSON text serializes one value: an object, array, string, number, boolean, or null. Parsing removes insignificant whitespace before the comparison begins. Objects are traversed by member name; arrays use the selected matching policy; primitives are compared at the resulting paths.
Transformation Core:
| Stage | Rule | Evidence |
|---|---|---|
| Parse | Each input must contain one valid JSON value. | Invalid syntax or empty input stops the comparison. |
| Traverse | Object names are sorted for stable walking; arrays follow index, primitive-multiset, or object-key matching. | Readable dot paths and JSON Pointer paths identify each compared value. |
| Apply policy | Ignore rules run before value comparison; optional number coercion applies only to primitive numeric strings. | Rows become Ignored, Unchanged, Changed, Type changed, Added, or Removed. |
| Bound evidence | At most 2,500 detailed rows are retained while total and truncated-row counts continue. | The ledger can signal that its captured detail is incomplete. |
Rule Core:
Array policy changes path identity. Index matching compares position with position. Primitive-multiset matching compares stable values and their occurrence counts, so order alone disappears. Object-key matching maps every object by the selected member; an absent or repeated key causes that array to fall back to positions and produces a note.
| Rule | Exact behavior | Consequence |
|---|---|---|
| Strict types | JSON type and value must both agree. | "42" and 42 are a type change. |
| Coerce numbers | A syntactically numeric string is converted to a number before primitive equality is checked. | "42" and 42 can become unchanged. |
| Exact ignore | A dot path or JSON Pointer matches one location. | Only that location is marked Ignored. |
| Prefix ignore | A trailing * matches every path beginning with the preceding text. | An entire subtree can be excluded. |
| Pointer escaping | ~ becomes ~0 and / becomes ~1 inside a reference token. | Member names remain addressable in JSON Pointer form. |
Formula Core:
The headline count reconciles the four material statuses. Ignored and unchanged rows never contribute to it.
For example, comparing {"a":1,"b":"x"} with {"a":2,"b":"x","c":true} under strict positional rules yields two material paths: $.a is changed and $.c is added. The corresponding pointer paths are /a and /c.
Each source is limited to 200,000 characters. Detailed row capture is bounded independently, so large trees can produce correct summary counts while retaining only the first 2,500 evidence rows.
Privacy Notes:
Parsing, file reading, structural comparison, and result generation happen in the browser. The comparison action does not upload pasted JSON or loaded file contents.
- Each selected JSON or text file must be no larger than 200 KB.
- Clipboard contents, screenshots, downloaded evidence, and copied page addresses can still expose secrets or customer data.
- Remove tokens, credentials, and private records before sharing any result artifact.
References:
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format, IETF, December 2017.
- RFC 6901: JavaScript Object Notation (JSON) Pointer, IETF, April 2013.