在线 JSON Diff 工具:比较和分析 JSON 数据差异
什么是 JSON Diff
JSON Diff 是比较两个 JSON 数据结构并找出差异的过程。它能识别出两个 JSON 对象之间的新增、删除和修改。把两段数据贴进我们的 JSON Diff 工具,即可并排高亮显示所有差异。
比较示例
原始 JSON:
{
"name": "张三",
"age": 28,
"hobbies": ["reading", "gaming"]
}
修改后的 JSON:
{
"name": "张三",
"age": 29,
"hobbies": ["reading", "coding"],
"email": "zhang@example.com"
}
Diff 结果:
{
"age": { "old": 28, "new": 29 },
"hobbies[1]": { "old": "gaming", "new": "coding" },
"email": { "added": "zhang@example.com" }
}
为什么需要 JSON Diff
- API 响应验证:比较 API 返回值与预期值(在线 JSON Diff 工具支持四档对比粒度,粘贴即比)
- 配置变更检测:对比配置文件的修改
- 数据迁移验证:确认数据迁移的正确性
- 代码审查:比较两个版本的 JSON 输出
- 自动化测试:在测试中断言数据变化
- 版本控制:追踪 JSON 数据的变更历史
Diff 结果类型
| 变更类型 | 说明 | 标识 |
|---|---|---|
| 新增 | 键不存在于原始 JSON | + 或 added |
| 删除 | 键存在于原始但不在修改后 | - 或 deleted |
| 修改 | 键存在但值不同 | ~ 或 changed |
| 未变 | 键和值都相同 | 无标记 |
如何使用在线工具
使用 ToolVault 工具匣 的 JSON Diff 工具:
- 在左侧输入原始 JSON
- 在右侧输入修改后的 JSON
- 工具自动比较并高亮显示差异
- 显示新增、删除、修改的具体内容
- 支持复制 Diff 结果,或一键复制 RFC 6902 JSON Patch
降噪对比:忽略数组顺序与忽略字段
对比 API 响应或日志时,真正想看的字段常被两类噪音淹没:顺序无关的数组(标签、权限列表)和每次必变的元字段(updatedAt、traceId)。工具面板提供三个选项:
- 忽略数组顺序:数组按内容多集匹配——
[1,2,3]和[3,1,2]无差异;剩余元素按「最小差异」两两配对,报成修改而不是「整行删除+整行新增」。 - 数组对齐键(如
id):配合忽略顺序使用,对象数组按业务键对齐,同id的行即使位置变了、其他字段改了,也能精确报出users[id=7].name级别的字段差异。 - 忽略字段:逗号分隔的字段名(任意层级生效),如
updatedAt, traceId——比对时直接跳过,让差异清单只剩信号。
判断标准不变:对顺序敏感的接口(时间线、榜单)不要开「忽略数组顺序」;不确定时先用默认按位置模式跑一遍。
导出 JSON Patch(RFC 6902)
差异清单是给人读的;给机器(CI 断言、变更回放)用的是 JSON Patch。点击「复制 JSON Patch」得到标准 add / remove / replace 操作序列,路径为 JSON Pointer(如 /config/timeout)。两个边界要知道:
- 开启「忽略数组顺序」时,数组路径是逻辑位置而非下标,无法映射成可执行 patch——该模式下不显示 patch 按钮,请改用 diff 清单。
- patch 文本内的大整数(如雪花 ID)按原文输出不丢精度;但任何经
JSON.parse消费 patch 的实现,数字仍受 IEEE 754 双精度限制——这是 patch 协议本身的边界,不是工具实现问题。
代码中的 JSON Diff
JavaScript
// 深度比较两个对象
function deepDiff(oldObj, newObj, path = '') {
const diffs = {};
const allKeys = new Set([...Object.keys(oldObj), ...Object.keys(newObj)]);
for (const key of allKeys) {
const currentPath = path ? `${path}.${key}` : key;
if (!(key in oldObj)) {
diffs[currentPath] = { type: 'added', value: newObj[key] };
} else if (!(key in newObj)) {
diffs[currentPath] = { type: 'deleted', value: oldObj[key] };
} else if (typeof oldObj[key] === 'object' && typeof newObj[key] === 'object') {
Object.assign(diffs, deepDiff(oldObj[key], newObj[key], currentPath));
} else if (oldObj[key] !== newObj[key]) {
diffs[currentPath] = { type: 'changed', old: oldObj[key], new: newObj[key] };
}
}
return diffs;
}
Python
def deep_diff(old, new, path=''):
diffs = {}
all_keys = set(list(old.keys()) + list(new.keys()))
for key in all_keys:
current_path = f"{path}.{key}" if path else key
if key not in old:
diffs[current_path] = {'type': 'added', 'value': new[key]}
elif key not in new:
diffs[current_path] = {'type': 'deleted', 'value': old[key]}
elif isinstance(old[key], dict) and isinstance(new[key], dict):
diffs.update(deep_diff(old[key], new[key], current_path))
elif old[key] != new[key]:
diffs[current_path] = {'type': 'changed', 'old': old[key], 'new': new[key]}
return diffs
行 diff 对 JSON 说谎的两种方式
一行的 minified JSON 没有行可 diff——行 diff 报告「全变了」;美化打印后的键重排(同一对象、字母序不同的序列化器)产生千行文本 diff 而语义零变化。修复是结构化:解析两侧、比较树、报告路径——对象键序不敏感(JSON 规范如此)、数组序敏感(语义如此)。我们的 JSON diff 做的就是结构化比较;它编码的纪律是:机器生成的 JSON 用行 diff 是选错了工具,行 diff 留给手编文件(行上下文有含义的场合)。
数组 diff 的对齐问题
朴素工具按位置 diff 数组:删了第 5 个元素,后面全部位移——一次插入报成 N 处变更。聪明的数组 diff(LCS 最长公共子序列,与文本 diff 同源)按内容对齐、报出那一次插入。代价:大对象数组的 LCS 昂贵,且「相似但不相等」的元素(同 id 不同字段)让朴素对齐失效——生产级答案是按 id 字段键对齐(把数组当 map diff)。你的 diff 工具在小改动上报出大面积数组变更,就是缺键对齐;用一个带 id 的样本一测便知。
规范化先行:稳定比较的礼仪
机器写的 JSON 因序列化器而异:键序、数字格式(1.0 与 1)、unicode 转义(\u0041 与 A)、无意义空白。规范化——先做规范序列化(键排序、数字标准化)再 diff——把这一整类噪音消除。RFC 8785(JSON 规范化方案)是正式规范;务实子集(排序键+规范数字)拿走 95% 的收益。先规范化的 diff 报信号;diff 裸字节的报序列化器癖好。diff 进自动化管线(发布说明、变更检测)时规范化不是可选项——否则每次序列化器升级都误报。
FAQ
JSON Diff 能处理大文件吗?
工具在浏览器本地做全量递归对比:几 MB 级的配置/响应对比是秒级;超过 10MB 的超大文件建议先用「忽略字段」裁掉无关子树,或先在本地用 jq 抽取关心的路径再对比。「忽略数组顺序」的剩余元素配对是 O(n²) 贪心策略,上千元素的乱序数组会明显变慢——元素有业务键时填上「数组对齐键」可大幅降低配对成本。
Diff 结果可以合并吗?
可以。点击「复制 JSON Patch」得到 RFC 6902 标准 patch(add / remove / replace),可被 fast-json-patch 等库直接 apply 回原始 JSON。注意「忽略数组顺序」模式下路径无下标语义,patch 不可用。
数组顺序变化怎么处理?
数组 Diff 有两种策略:按位置比较(默认,严格但受顺序影响)和按内容比较(勾选「忽略数组顺序」,顺序无关但牺牲位置信息)。元素是带 id 的对象时,再填「数组对齐键」按业务键对齐,可同时获得「顺序无关」和「字段级精确差异」。
实现注记
做这个工具时踩过一个大整数坑:解析必须走无损模式(保留数字原文),比较时同值大整数按 raw 原文判等——如果按解析产物的实例引用比较,两个数值相同的大整数 ID 也会被报成 modified,纯属假差异。
ToolVault 工具匣 出品的开发者指南。其他在线工具可在 首页 找到。
相关工具
相关文章
在线 CSV 转 SQL 工具:将表格数据导入数据库
CSV 转 INSERT:空单元格→NULL、MySQL 反引号或 PostgreSQL 双引号、BOM 剥离、Markdown 竖线转义,以及与 COPY/LOAD 的分工。
HTML 表格转 JSON 怎么保留行列结构?
把网页里的 HTML 表格转成 JSON,怎么保留表头、处理合并单元格、保持嵌套结构?逐步方法并附本站 HTML 表格转 JSON 工具。
Excel 转 JSON 后日期变成数字 / 中文乱码,怎么办?
把 Excel 转成 JSON 时日期变 44927 这种数字、中文乱码、空单元格丢失怎么办?讲清 Excel 日期序列号与编码坑,并附本站 Excel 转 JSON 工具。