JSON 差异对比
JSON对比两份 JSON 文档,并高亮结构差异。
本页内容
什么是 JSON Diff?#
JSON Diff 对比两份 JSON 文档,准确地告诉你它们之间到底变了什么——哪些字段冒出来了、哪些字段没了、哪些路径还在但值变了。它是文本 diff 的结构化版本:不是逐行匹配,而是遍历对象和数组这棵树,所以一个值从 1 变成 2,会被精确定位成某个路径上的一处编辑,而不是一整段文本被重写。
只要 JSON 是某种会演进之物的传输格式,这件事就有用:两次部署之间的 API 响应、两次修改之间的配置文件、测试套件里的 fixture、每天导出的数据。两份美化后的文档并排摆着、肉眼比对,只对小文档管用;嵌套一旦深了,你需要的是把差异一条条列出来。
要注意的是,JSON diff 对数组的顺序敏感。两个数组只有在每个位置上的元素都一一相等时才算相等——这是 JSON 本身对相等的定义。所以 [a, b] 和 [b, a] 是不同的,diff 会报出来:顺序有意义时(比如一组步骤)这很有用,顺序无意义时(比如一个被塞进数组的集合)会让人意外。
怎么使用#
- 把原文档粘进 左侧(原文)(Left (original)),把修改后的文档粘进 右侧(改动后)(Right (changed))。
- 边输入边实时比较。你也可以点 比较(Compare)强制刷新一次。
- 输出区把每条差异各占一行:
- Added(新增)——该路径只在右侧存在,行内显示新值。
- Removed(删除)——该路径只在左侧存在,行内显示旧值。
- Changed(改动)——两侧都存在但值不同,行内显示
旧 → 新。 每行前面带一个 JSONPath 风格的路径,比如$.version或$.tags[2],方便你定位到任一文档里的对应位置。
- 如果两份文档深度相等,状态栏会明确写”无差异”,而不是扔一个空输出区让你自己猜。
- 点 示例(Sample)载入一对真实的”前后”文档;点 清空(Clear)重置两边和结果。
主要特性#
- 结构化、非文本化。 比较的是解析后的值树,所以重新缩进、调换对象键的顺序、改空白,都不会产生假差异。
- 路径精确。 每条改动都带 JSONPath 记法的位置——
$是根,.key是对象字段,[i]是数组下标——你可以直接跳到正确位置。 - 三种改动类型。 新增、删除、改动分开报告并配色,让新增一眼区别于删除和编辑。
- 分侧报错。 如果某一侧不是合法 JSON,状态栏会点名是哪一侧失败了(
左侧输入不是合法 JSON。),而不是抛一团含糊的错误。 - 实时比较。 编辑任一侧时 diff 都跟着更新,迭代 fixture 或响应很顺手。
实例演示#
点 示例,两个输入框分别填上一份小型配置文档修改前后的版本:
左侧
{
"name": "ArpGate",
"version": 1,
"tags": ["json", "encoding"],
"features": { "static": true, "backend": null }
}
右侧
{
"name": "ArpGate",
"version": 2,
"tags": ["json", "encoding", "crypto"],
"features": { "static": true, "backend": false, "offline": true }
}
diff 把变化逐条列出来:
changed $.version 1 → 2
added $.tags[2] "crypto"
changed $.features.backend null → false
added $.features.offline true
注意什么没出现:$.name(没变)、$.tags[0] 和 $.tags[1](没变)、$.features.static(没变)。相等的分支不产出,所以哪怕两份文档各有好几个字段,四行 diff 就是全部故事。如果你再把两栏设成同一份文档,状态栏会切换成”无差异——两侧完全相同”。
常见问题#
为什么重排过顺序的数组会显示成全部改动?#
JSON 数组是有序的,相等性是按位置的。[1, 2] 和 [2, 1] 在下标 0 和下标 1 处都不同,所以 diff 会报两处改动。对顺序有意义的序列来说这是对的。如果你的数组其实代表一个集合,先在两份文档里排序(或归一化)再比,否则挪动会被看成编辑。
它能识别对象键被改名了吗?#
它会报成”一处删除 + 一处新增”,因为 JSON 没法表达”这个键变成了那个键”。把 enabled 改名成 active,会显示成 removed $.enabled 和 added $.active——两行,而不是一行”改名”。这才是数据变化的诚实表达。
类型变化长什么样?#
显示成单条 changed。一个值从字符串 "36" 变成数字 36,diff 会在该路径显示 "36" → 36——两侧序列化的差异把类型翻转暴露出来。null 变 false、数字变成对象,同理。
它能告诉我哪些字段没变吗?#
不能,这是故意的。把所有没变的字段也列出来,会在真实文档里把真正的改动淹没在噪声中。diff 只展示增量,相等的分支保持沉默。如果你要看某份文档的完整结构,用树形查看器。