Comparing JSON Data:
Deep Equality & Semantic Diff
Two JSON objects can look different as text but be semantically identical. Here's how to compare them the right way — whether you're writing tests, reviewing config changes, or debugging API responses.
The Problem
You've got two JSON files open side by side. They look similar — same general shape, same kind of data — but you need to know if they're actually the same. Maybe you're comparing staging vs production API responses. Maybe a teammate updated a config file and you're reviewing the diff. Or you're writing a test that checks if your function output matches the expected result.
Comparing JSON isn't as straightforward as running diff on two text files. JSON objects are unordered collections — {"a":1,"b":2} and {"b":2,"a":1} mean exactly the same thing, but a text diff will flag every line as changed. And when you're dealing with deeply nested objects, hundreds of keys, or values that differ in subtle ways, you need more than a line-by-line comparison.
This guide covers the three ways to compare JSON — text diff, structural comparison, and semantic diff — and which one to use depending on what you're trying to accomplish.
Why Plain Text Diff Falls Short
Most developers reach for diff or a visual diff tool first. It works great for source code. For JSON, not so much. Here's why.
Text diff compares files line by line. It doesn't understand JSON structure. Two identical JSON objects with different key ordering will produce a messy diff showing every line as added, removed, and added again. That's useless when what you actually want to know is: "did any values change?"
The same problem occurs with whitespace. Formatted JSON with 2-space indentation and the same JSON with 4-space indentation will produce a diff on every line, even though the data is identical. A text diff also can't tell you that 1 and 1.0 are numerically equal, or that null and a missing key might be treated differently by your application.
Use a text diff when: you need a quick visual of where two JSON strings differ in raw form, or you're comparing JSON schemas where key order is part of the spec. For everything else, use a structural approach.
Deep Equality: Are These Two Objects the Same?
Deep equality comparison answers a simple question: do these two JSON objects have the same structure and the same values? It doesn't care about key order, whitespace, or formatting — it cares about the actual data.
A proper deep comparison walks both objects recursively and checks:
- Same keys — both objects have the same set of keys at every level, regardless of order
- Same types —
42vs"42"is a difference (number vs string) - Same values — primitive values match exactly; nested objects and arrays are compared recursively
- Same array elements — arrays are compared by position, so
[1,2,3]≠[3,2,1]
This is the right tool for test assertions. You expected {"status":"ok","data":[...]} and you got {"data":[...],"status":"ok"} — deep equality says they match. Your test passes.
The JSON Compare tool does exactly this. Paste your two JSON objects, click Deep Compare, and you get an immediate yes or no. If they don't match, switch to Diff mode to find out why.
Semantic Diff: Finding What Actually Changed
Deep equality tells you if two objects differ. A semantic diff tells you where and how. It walks both objects and reports every key that exists in one but not the other, every value that changed, and every type mismatch.
This is the tool for code review. When someone updates a JSON config file, you want to see: "they added a timeout key under server, changed port from 3000 to 8080, and removed debug entirely." Not 47 lines of re-indented noise.
For the JSON Compare tool's Diff mode, the output uses a clear notation:
+ server.timeout: 5000— key added in B- server.debug: true— key removed from Aserver.port: 3000 → 8080— value changed
This is also helpful for comparing API responses across environments. Your staging server returns slightly different data than production — the diff shows you exactly which fields, so you can decide if the differences are expected or a bug.
Sorting Keys Before Comparison
A quick trick that makes diff tools work better: sort your JSON keys first. If both files have keys in the same alphabetical order, a plain text diff becomes much more useful. The structural differences stand out because you've eliminated the ordering noise.
The JSON Sort tool does this recursively — every object at every nesting level gets its keys sorted A→Z. Run it on both files, then compare the sorted versions. This won't catch all semantic differences (it still can't tell you that 1 and 1.0 are the same), but it's fast and works with any diff tool.
Many teams add key sorting to pre-commit hooks. Before a JSON config file is committed, its keys are sorted automatically. This eliminates the most common source of diff noise: two developers saving the same file with different key ordering.
Comparing Large JSON Files
When you're comparing JSON files with thousands of keys, the approach changes. Loading both files into a comparison tool and scrolling through the results doesn't scale.
For large datasets, consider:
- Normalize first. Sort keys, format consistently. This eliminates false positives before comparison starts.
- Focus on structure, not values. Check that both files have the same keys at the same paths. If the structure matches, you can spot-check individual values.
- Use checksums for equality. If you just need to know whether two large JSON files are identical, compute a hash of the sorted, minified version. Identical hashes mean identical content.
- Sample for differences. If the files are too large for a full comparison, spot-check representative sections — the first 10 records in an array, the deepest nested objects, any sections known to vary between environments.
Common Comparison Pitfalls
NaN, Infinity, and Undefined
JSON doesn't support NaN, Infinity, or undefined. If your comparison tool is processing raw JavaScript objects (not JSON strings), these values can appear and cause confusing results. Always work from the JSON string — parse it, then compare the parsed result.
Date Strings vs Date Objects
JSON has no date type. Dates are strings like "2024-01-15T10:30:00Z". Two date strings with different timezone formats might represent the same moment but won't match in a string comparison. Before comparing, decide whether you're comparing the string representation or the underlying timestamp.
Numeric Precision
JSON numbers are double-precision floats. 0.1 + 0.2 equals 0.30000000000000004 in JavaScript, and two JSON files might contain slightly different floating-point representations of the same logical value. For numeric comparisons, consider whether exact equality or approximate equality is appropriate.
Quick Reference
| What You Need | Approach | Tool |
|---|---|---|
| Are these equal? (yes/no) | Deep Compare | JSON Compare |
| What changed? (specific keys/values) | Diff mode | JSON Compare |
| Keys in consistent order | Sort before comparing | JSON Sort |
| Visual line-by-line diff | Text diff | Diff Checker |
| Validate before comparing | Format + Validate | JSON Formatter |