UtilityToolsLab

© 2026 UtilityToolsLab. Built and maintained by the UtilityToolsLab Team.

About·Changelog·Privacy Policy·Terms of Service·Report a bug
HomeCode & DevJSON Diff Checker

Related Tools

JSON FormatterBase64UUID GeneratorJWT DecoderTimestampRegex TesterRandom JSON GeneratorAPI Load TesterXML Formatter

JSON Diff Checker & Compare Tool

Compare two JSON payloads structurally and read every added, removed or retyped key by its path, beside a unified view of the merged document.

You Might Also Like

All Code & Dev

JSON Formatter

Paste raw JSON to instantly format, beautify, validate and minify it. Syntax errors are pinpointed by line and column. Free and fully private.

Base64

Encode text or data to Base64 and decode Base64 strings back to readable text. A fast developer utility for API payloads, tokens and data URIs.

UUID Generator

Generate RFC 4122 compliant UUID v4 strings with one click, or batch-generate up to 100 unique IDs at once. Cryptographically random and free.

JWT Decoder

Decode and inspect JSON Web Tokens. View header, payload, and signature. Detects expiry and maps all registered JWT claims.

Two payloads that differ in a single value can look completely unrelated to a line-based diff, because whatever wrote the second one sorted the keys and reindented the file on its way out. JSON Diff Checker compares the parsed structures rather than the characters. Key order stops mattering. Whitespace stops mattering. What survives is a list of the paths whose values genuinely moved.

Each difference is reported in two shapes, because the two answer different questions. The change list names every one by JSON path, so $.env.LOG_LEVEL tells you where to look in a 400-line manifest without scrolling for it. The unified view redraws the merged document with deleted lines marked − and inserted lines marked +, which is the shape you already read in a pull request.

Arrays are where comparers usually go wrong. A slot-by-slot match is correct for an ordered list and badly wrong for a set of feature flags that some serialiser shuffled, so one toggle switches to matching items by value instead. Parsing happens in the JavaScript engine already running this page. A production config with live credentials in it goes nowhere.

Walkthrough: A Deploy Manifest Bumped by One Version

Press Load Sample and two revisions of the same service manifest drop in. Both open on "service": "checkout-api". The original sits at "version": "2.4.0" with 3 replicas; the modified one reads "2.5.1" and asks for 5. Four stat cards settle on 2 added, 1 removed, 3 changed, 5 identical.

The change list spells out which is which. $.env.RETRIES and $.features[2] are the two additions. The single deletion is $.owner.oncall, which held ana.ruiz@harbourline.dev before someone dropped the field. The three edits are the version string, the replica count, and $.env.LOG_LEVEL moving from info to debug. Five paths matched on both sides and stay hidden until you ask to see them.

The Controls Above the Two Boxes

  • Swap Sides reverses the two payloads, turning every addition into a deletion. It is the quickest way to check that a rollback removes exactly what the release added.
  • Pretty-Print Both rewrites each side at two-space indentation. A minified response body pasted straight from a network tab is unreadable next to a formatted file, and this puts them on equal footing before you compare.
  • Ignore array order matches array items by value, so ["x","y","z"] against ["z","y","x"] reports nothing instead of two edits. Only real insertions and deletions survive it.
  • Ignore string case folds string values before comparing, which stops an environment variable written as INFO on one side from reading as a change.
  • Show identical keys adds the matched paths back into the list. Useful when you are proving a migration changed nothing, rather than hunting for what it broke.
  • Five filter chips sit above the list and carry live counts, so Removed with a count of 1 narrows a long report to the one deletion in it.
  • Every path in the list is a button. Click $.owner.oncall and that path alone lands on your clipboard, ready to paste into a jq expression or a test assertion. Almost nobody discovers this on a first visit.

Tricky Inputs That Two Parsers Disagree On

  • Repeat a key inside one object and JSON.parse keeps the last value silently. Both boxes are scanned for this before the comparison runs, and {"x": 1, "x": 2} raises an amber notice naming the key, because the value you wrote first is already gone by the time any diff sees it.
  • 1 and 1.0 are reported as identical. Both parse to the same double, and JSON carries no separate integer type to tell them apart.
  • Whole integers above 9007199254740991 are rounded on entry, so 9007199254740993 arrives as ...992 and two different record IDs can compare as unchanged. A warning names the first literal it finds.
  • A retyped value gets its own badge: "8080" against 8080 is one change tagged string to number, not a deletion plus an addition.
  • Each side accepts 200,000 characters. Past that you get Each side is capped at 200,000 characters. Trim this payload and paste it again. and the comparison stops rather than freezing the tab.
  • Nesting is followed to 64 levels. Anything below that is compared whole and shown as a single row flagged depth limit, so a recursive structure cannot exhaust the stack.
260 charsValid object
247 charsValid object

Added

2

Removed

1

Changed

3

Identical

5

Changes by Path
~ Changed

− "2.4.0"

+ "2.5.1"

~ Changed

− 3

+ 5

~ Changed

− "info"

+ "debug"

+ Added

+ 2

+ Added

+ "klarna"

− Removed

− "ana.ruiz@harbourline.dev"

Unified View
{
  "service": "checkout-api",
−  "version": "2.4.0",
+  "version": "2.5.1",
−  "replicas": 3,
+  "replicas": 5,
  "env": {
−    "LOG_LEVEL": "info",
+    "LOG_LEVEL": "debug",
    "TIMEOUT_MS": 3000,
+    "RETRIES": 2
  },
  "features": [
    "apple-pay",
    "gift-cards",
+    "klarna"
  ],
  "owner": {
    "team": "payments",
−    "oncall": "ana.ruiz@harbourline.dev"
  }
}