🔍 JSON Diff (结构比较)
结构化比较两个 JSON,并以 JSON Pointer 路径显示新增、删除、变更。支持键排序、数组顺序忽略、类型变化检测。
完全免费
无需注册
浏览器内完成
5 种语言
深色模式
🔒 关于隐私
- ・所有处理均在您的浏览器中完成
- ・输入数据绝不会发送到任何服务器
差异结果
🔗 相关工具
📖 常见的坑
把两份 JSON 作为结构进行比较,并为每处新增、删除、变更标注 JSON Pointer。处理全部在浏览器内完成。它与文本 diff 看的东西不同:缩进或换行的差异在这里不算差异。反过来,逐字完全相同的两份文档也可能在结构上不同,反之亦然——不弄清这条界线,就会误读结果。
| 情形 | 会发生什么 | 怎么处理 |
|---|---|---|
| 在数组开头插入一条,结果全部元素都被标成「变更」 | 数组是按下标逐位对齐的。在开头插入一条,后面的元素就全部平移一位,于是产生「/0 变更、/1 变更、…、末尾新增一条」这种难以阅读的差分。文本 diff 之所以能说「插入了一行」,是因为它计算了最长公共子序列(LCS),而结构比较不做这件事。元素一多到几十条,整份差分就全红,实际上没法读了。 | 请切换到「数组顺序:忽略」——这样会按集合比较,仅仅重排的内容就会显示为「无变化」。但当顺序本身有意义时(步骤、优先级、排名)就不能这么做。实务中最见效的一招是比较之前先按 id 把两边排序对齐:API 响应往往并不保证顺序,把这种顺序抖动当成差分展示出来,对判断毫无帮助。读差分的一个经验法则:若所有条目都被标为变更,请先怀疑「对齐失败」,而不是相信「真的全变了」。 |
| 看起来一样的数字被标成变更,真正不同的却没被标出 | JSON 不区分整数与浮点数。1 与 1.0 解析后是同一个值,不会产生差分;而字符串 "1" 与数字 1 在「类型变化:严格」下是两回事。API 响应里某字段在字符串与数字之间反复横跳并不罕见——把大整数编码成字符串以安全传输是常见设计。更危险的是相反的情形:JavaScript 的 Number 无法精确表示超过 2 的 53 次方的整数,因此 9007199254740993 与 9007199254740992 在解析那一刻就变成同一个值,差分完全不会出现。 |
若只是想容忍类型抖动,请切换到「类型变化:宽松」。但大整数的问题影响的是所有经过 JavaScript 的比较,而不只是这个工具。若数据中含有 Snowflake ID、快照版本号,或以最小货币单位的整数表示的金额,就必须在比较前把这些字段当作字符串处理——给解析器传 reviver,或者把它们排除出来单独检查。识别很简单:只要数值超过 16 位就该起疑——2 的 53 次方是 9,007,199,254,740,992,正好 16 位。 |
| 被「null」和「键不存在」的区别反复折腾 | {"a": null} 与 {} 在结构上确实不同,因此会报出差分。这是正确的行为,但真实系统往往并不区分两者,于是涌出大量无意义的条目。根源在语言:JavaScript 的 JSON.stringify 会丢弃值为 undefined 的键,而 Python 的 json.dumps 会把 None 输出为 null。表达同一个「没有值」,一边把键整个删掉,另一边留下一个 null。跨语言比较 API 时,差分几乎必定在这里膨胀。 |
比较之前先归一到其中一种约定。实务上,把两边值为 null 的键都剥掉最好处理——这等于把「缺失」与「null」视为同一,所以只在该前提成立的数据上这么做。但若 API 有意区分两者,则绝不可归一化。在 PATCH 语义中,{"a": null} 表示「删除 a」,而省略该键表示「不要动 a」(JSON Merge Patch,RFC 7386)。抹平这个区别,由差分生成的更新请求就会删掉你从未碰过的字段。能否归一化,永远由对端 API 的规格决定。 |
JSON Pointer(RFC 6901)有转义规则:键中的 ~ 写作 ~0,/ 写作 ~1。凡是以 URL 或文件路径为键的字典都会撞上这一点——指向 {"https://example.com/a": 1} 那个键的 Pointer 是 /https:~1~1example.com~1a。把界面上显示的 Pointer 直接粘进代码,忘了反转义就会指到完全不同的路径上,请留意。关于顺序还有一点:JSON 对象的键顺序按规范并无意义,但多数解析器会保留插入顺序。因此键顺序的差分传达的是「含义未变,但生成方变了」这一信息,可作为「库升级了」或「换了序列化器」的线索——在把它当噪音忽略之前,值得先弄清它为什么变了。
📖 使用方法
-
1
粘贴两个 JSON将旧版本粘贴到左侧,新版本粘贴到右侧。示例按钮可加载演示数据。
-
2
调整选项选择视图(树形 / 扁平 / unified)、是否忽略键顺序或数组顺序,以及类型比较的严格性。
-
3
查看差异新增 (+)、删除 (-)、变更 (~) 以颜色和 JSON Pointer 路径显示。摘要可一目了然。
❓ 常见问题
什么是 JSON Pointer?
RFC 6901 定义的以斜杠分隔的路径表示法,用于指向 JSON 中的任意值。例如 /users/0/email。
忽略数组顺序有何不同?
将数组视为集合,相同内容不同顺序视为一致。当只关心内容而非顺序时很有用。
字符串 "1" 与数字 1 如何比较?
严格模式下视为变更;宽松模式下视为相等。当需要容忍 API 响应的类型差异时切换到宽松模式。
🐛 此工具出现问题了吗?
免费、无需注册。仅提供复现步骤也有帮助。报告将直接发送给运营者并用于改进。
✅
感谢您的反馈!
已送达运营者,将用于改进工具。