How to Compare Two JSON Files
โ Back to Blog
How to Compare Two JSON Files
ยท 5 min read
Core Challenges of JSON Comparison
Comparing JSON files is more complex than comparing plain text files because JSON semantic equivalence is not the same as string equivalence. Two JSON objects with different field ordering may be completely semantically equivalent ({"a":1,"b":2} and {"b":2,"a":1} are the same JSON object). But if compared with a plain text diff tool, they'd be considered different โ producing many false positive "differences."
Similarly, JSON with different formatting (indentation, line breaks, spacing) differs at the text level but is semantically identical. This is why you need JSON-aware diff tools rather than simply using the diff command on two files. Understanding this distinction is the prerequisite for choosing the right comparison method.
Command-Line Comparison with jq
jq is the most powerful tool for command-line JSON comparison. Combined with jq -S (sort keys) and the standard diff command, you can achieve semantic comparison that ignores field ordering:
# ๅบๆฌ่ฏญไนๆฏ่พ๏ผๅฟฝ็ฅๅญๆฎต้กบๅบๅๆ ผๅผๅทฎๅผ๏ผ
# Semantic comparison (ignores field order and formatting differences)
diff /dev/null; then
echo "JSONs are identical"
else
echo "JSONs differ"
fi
Deep JSON Comparison in JavaScript
In JavaScript/Node.js, using === directly to compare two objects only compares references, not content. Deep comparison is needed to confirm whether two JSON values are semantically equivalent:
// ไฝฟ็จ JSON.stringify + ๆๅบ้ฎ๏ผ็ฎๅๅบๆฏ๏ผ
// Using JSON.stringify + sorted keys (simple scenarios)
function jsonEqual(a, b) {
return JSON.stringify(sortKeys(a)) === JSON.stringify(sortKeys(b));
}
function sortKeys(obj) {
if (Array.isArray(obj)) return obj.map(sortKeys);
if (obj && typeof obj === 'object') {
return Object.fromEntries(
Object.entries(obj).sort().map(([k, v]) => [k, sortKeys(v)])
);
}
return obj;
}
// ไฝฟ็จ fast-deep-equal ๅบ๏ผๆจ่๏ผๅค็่พน็ผๆ
ๅต๏ผ
// Using fast-deep-equal library (recommended, handles edge cases)
import equal from 'fast-deep-equal';
console.log(equal(obj1, obj2)); // true/false
// ไฝฟ็จ deep-diff ๅบ่ทๅ่ฏฆ็ปๅทฎๅผ
// Using deep-diff library for detailed differences
import { diff } from 'deep-diff';
const differences = diff(obj1, obj2);
// differences ๆฏๅๆดๆฐ็ป๏ผๆฏไธชๅ
็ด ๅ
ๅซ่ทฏๅพใ็ฑปๅใๆงๅผใๆฐๅผ
JSON Comparison in Python
Python's JSON comparison is very concise because Python's dictionary comparison naturally ignores key ordering:
import json
# ๅ ่ฝฝๅนถๆฏ่พ๏ผPython dict ๆฏ่พๅฟฝ็ฅ้ฎ้กบๅบ๏ผ
# Load and compare (Python dict comparison ignores key order)
with open('file1.json') as f:
obj1 = json.load(f)
with open('file2.json') as f:
obj2 = json.load(f)
print(obj1 == obj2) # True if semantically equal
# ่ทๅ่ฏฆ็ปๅทฎๅผ
# Get detailed differences
def json_diff(obj1, obj2, path=""):
if type(obj1) != type(obj2):
print(f"{path}: type changed {type(obj1).__name__} โ {type(obj2).__name__}")
return
if isinstance(obj1, dict):
for key in set(obj1) | set(obj2):
if key not in obj1:
print(f"{path}.{key}: added = {obj2[key]}")
elif key not in obj2:
print(f"{path}.{key}: removed = {obj1[key]}")
else:
json_diff(obj1[key], obj2[key], f"{path}.{key}")
elif isinstance(obj1, list):
for i, (a, b) in enumerate(zip(obj1, obj2)):
json_diff(a, b, f"{path}[{i}]")
if len(obj1) != len(obj2):
print(f"{path}: length changed {len(obj1)} โ {len(obj2)}")
elif obj1 != obj2:
print(f"{path}: {obj1!r} โ {obj2!r}")
API Response Comparison: Usage in Testing
In API testing, comparing response JSON is a common requirement: verifying that interface behavior is consistent before and after refactoring, or comparing responses across different environments (staging/production). Usually you need to ignore dynamic fields (like timestamps, request IDs) before comparing:
# ไฝฟ็จ jq ๅฟฝ็ฅๅจๆๅญๆฎตๅๆฏ่พไธคไธช API ๅๅบๅฟซ็
ง
# Using jq to ignore dynamic fields before comparing two API response snapshots
IGNORE_FIELDS='del(.meta.timestamp, .meta.requestId, .data.updatedAt)'
diff \
/tmp/old.json
git show HEAD:config.json | jq -S . > /tmp/new.json
diff /tmp/old.json /tmp/new.json
JSON Patch: Standard Format for Describing JSON Differences
RFC 6902 defines the JSON Patch format for describing a sequence of operations (add, remove, replace, move, copy, test) to apply to a JSON document. This is not just a standard way to represent "differences" โ it can also serve as the API's PATCH request format, precisely describing modifications the client wants to make to a resource:
In scenarios requiring precise tracking and replay of JSON change history (like collaborative editing, configuration change auditing), JSON Patch is more useful than simple "before and after comparison": you can apply a series of Patch operations step by step for fine-grained version control and change rollback. Combined with RFC 7396's JSON Merge Patch (a simpler partial update format), most API PATCH operation needs can be met.
// JSON Patch ็คบไพ / JSON Patch example
[
{ "op": "replace", "path": "/user/name", "value": "Bob" },
{ "op": "add", "path": "/user/phone", "value": "+1-555-0100" },
{ "op": "remove", "path": "/user/legacy_field" }
]
// ไฝฟ็จ fast-json-patch ๅบๅบ็จ Patch
import jsonpatch from 'fast-json-patch';
const patched = jsonpatch.applyPatch(originalDoc, patchOps).newDocument;
// ็ๆไธคไธชๅฏน่ฑกไน้ด็ Patch
const patch = jsonpatch.compare(originalDoc, modifiedDoc);
Try the online tool now โ no installation, completely free.
Open Tool โ
Try the free tool now
Use Free Tool โ