跳至内容

JSON比较工具 - 在线免费比较JSON | JSON差异对比

该工具可在线免费比较两个JSON对象或文件,逐项列出新增、删除和修改的所有数值,并以颜色标注差异类型,同时用类似JSON路径的表达式标明每处差异在数据结构中的具体位置。比较过程完全在浏览器本地进行,无需注册,适合调试API响应、核对配置文件版本以及排查数据同步问题等场景。

JSON 差异工具

加载计算器...
📚

文档

JSON 比较工具通常称为 JSON 差异工具,用于比较两个 JSON(JavaScript 对象表示法)值,并报告它们之间发生的变化。它会列出每个新增、删除或修改的属性或数组项,并给出其在数据中的确切位置。本页通过基于实际比较逻辑的示例,说明 whiz.tools 的 JSON 比较工具如何工作。

什么是 JSON 比较?

JSON 比较是指对照检查两个 JSON 文档,以找出差异的过程。JSON 文档是一段由对象(花括号中的键值对)、数组(方括号中的有序列表)和字符串、数字、布尔值、null 等原始值构成的文本。当文档超过几行后,凭肉眼比较会变得缓慢且容易出错,因此比较工具会自动进行匹配并突出显示每项变化。

开发人员使用这种比较来检查 API 响应、跟踪配置文件的变化、验证数据迁移是否丢失信息,以及审查版本控制中 JSON 文件的修改。

工具如何比较两个 JSON 值

工具先使用标准 JSON 解析器解析两个输入,然后逐层同时遍历生成的两个值。每一步按以下顺序提出三个问题:

  1. 两个值的类型是否不同(例如一个是对象,另一个是数字),或者其中一个是 null 而另一个不是?如果是,工具会在该位置记录一次修改,并停止向更深层比较。
  2. 两个值是否都是原始值(字符串、数字、布尔值或 null)?如果是,工具会直接比较它们。任何差异都算作修改,包括从数字 123 变为字符串 "123"。
  3. **两个值是否都是对象或都是数组?**如果是,工具会根据以下规则比较其内容,并递归比较其中嵌套的对象或数组。

每个差异都会记录一个路径,例如 user.address.city 或 tags[1],因此很容易在原始文档中找到。对象成员之间用点号连接,数组项则用方括号中的索引表示。若文档最顶层出现差异,例如数组被对象替换,数据内部没有可用路径,因此会标记为 $。这是 RFC 9535(JSONPath 标准)定义的根标识符,表示整个文档。

比较对象

对于两个 JSON 对象,工具会收集任一对象中出现的所有键。对于每个键:

  • 如果该键只存在于第二个对象中,则它是一个新增属性。
  • 如果该键只存在于第一个对象中,则它是一个删除属性。
  • 如果该键同时存在于两个对象中,工具会递归比较这两个值。

键的顺序不影响结果。JSON 标准没有规定对象成员的顺序,因此 {"a":1,"b":2} 和 {"b":2,"a":1} 会被视为相同。

比较数组

数组按位置而不是按内容进行比较。工具会逐个索引遍历两个数组,比较每个索引处的值,直到较长数组的末尾。如果一个数组较短,较长数组末尾多出的项会被报告为新增或删除。

这意味着工具从不尝试根据数组项的内容进行匹配。它不会发现某个对象从索引 1“移动”到了索引 2;它只会看到每个索引处的值发生了变化。在数组中间删除或插入一项,会使后续每一项都向前或向后移动一个位置,因此通常会显示为多项分别修改,而不是一次明确的新增或删除。

计算示例

示例 1:比较两个对象

第一个 JSON:

1{ "user": { "address": { "city": "New York", "zip": "10001" } } }
2

第二个 JSON:

1{ "user": { "address": { "city": "Boston", "zip": "02108" } } }
2

结果:

  • 已修改 user.address.city:"New York" → "Boston"
  • 已修改 user.address.zip:"10001" → "02108"

示例 2:数组末尾发生变化

第一个 JSON:

1{ "tags": ["important", "urgent", "review"] }
2

第二个 JSON:

1{ "tags": ["important", "critical", "review", "documentation"] }
2

索引 0 未改变,索引 1 发生变化,索引 2 未改变,索引 3 仅存在于第二个数组中。结果:

  • 已修改 tags[1]:"urgent" → "critical"
  • 已新增 tags[3]:"documentation"

示例 3:从数组中间删除一项

本示例展示从数组中间删除一项时会发生什么,因为这是一种常见的困惑来源。

第一个 JSON:

1{
2  "products": [
3    { "id": 1, "name": "Laptop", "price": 999.99 },
4    { "id": 2, "name": "Mouse", "price": 24.99 },
5    { "id": 3, "name": "Keyboard", "price": 59.99 }
6  ]
7}
8

第二个 JSON,其中删除了“Mouse”项,并在末尾添加了“Monitor”项:

1{
2  "products": [
3    { "id": 1, "name": "Laptop", "price": 899.99 },
4    { "id": 3, "name": "Keyboard", "price": 59.99 },
5    { "id": 4, "name": "Monitor", "price": 349.99 }
6  ]
7}
8

看到这些内容时,人们会说“删除了 Mouse,添加了 Monitor”。但由于工具严格按索引比较,它不会这样判断。它会将索引 0 与索引 0、索引 1 与索引 1、索引 2 与索引 2 分别进行比较,因此被删除项之后的每个字段都会与错误的对象对齐。实际结果是七项修改:

  • 已修改 products[0].price:999.99 → 899.99
  • 已修改 products[1].id:2 → 3
  • 已修改 products[1].name:"Mouse" → "Keyboard"
  • 已修改 products[1].price:24.99 → 59.99
  • 已修改 products[2].id:3 → 4
  • 已修改 products[2].name:"Keyboard" → "Monitor"
  • 已修改 products[2].price:59.99 → 349.99

要在比较此类列表时获得更清晰的结果,请先以相同方式对两个数组排序或设置键,例如将两个列表按相同顺序排列,或在比较前根据 ID 字段匹配对象。

工具不会执行的操作

  • **它不会根据内容匹配数组项。**如上所示,它完全按索引位置比较,因此无法识别某项是移动了而不是发生了变化。
  • **它不会检测循环引用。**这在实际使用中并不构成限制:两个输入都来自 JSON.parse,该函数始终构建普通树结构,不可能生成引用自身的值。有效 JSON 文本本身也不可能包含循环引用。
  • **它不提供比较前对数组排序的设置。**在粘贴输入前重新排列数组项,是避免上述索引偏移影响的唯一方法。

如何使用工具

  1. 将第一个 JSON 文档粘贴到左侧文本框,将第二个粘贴到右侧文本框。
  2. 当两个文本框都包含文本后,工具会自动比较;也可以点击“比较”手动运行。
  3. 阅读结果列表。每一行都会显示一个路径,例如 user.age,以及它是新增、删除还是修改,并将旧值和新值并排显示。
  4. 点击“复制”,以纯文本形式复制结果。

如果文本框中的内容不是有效 JSON,工具会在该文本框下方显示错误,而不是进行比较。如果两个文本框中的内容都无效,两个错误会同时出现。

常见问题

两个 JSON 值之间什么算作差异? 如果某个属性或数组项只存在于两个文档中的一个,或者同时存在但值或类型不同,则它们存在差异。将值从数字 5 改为字符串 "5" 算作修改,即使它们看起来可能相似。

项的顺序重要吗? 这取决于容器。JSON 对象没有规定成员顺序,因此两个对象即使键和值的顺序不同,只要内容相同,也会被视为相同。数组是有序的,工具按索引位置比较数组,因此将某项移动到其他位置会被报告为一系列修改,而不是移动。

结果路径 $ 表示什么? 它表示整个文档发生了变化,而不是其中某一部分发生变化。当两个输入在顶层属于不同类型的值时,就会出现这种情况,例如一侧是数组,另一侧是对象,或者两个普通数字 1 和 2。$ 是 RFC 9535(JSONPath 标准)中的根标识符。

我的 JSON 数据会发送到服务器吗? 不会。比较在浏览器中使用 JavaScript 运行,不会上传任何内容。

缩进或压缩等格式会影响结果吗? 不会。两个输入都会先解析为 JSON 值,然后再进行比较,因此空白、缩进和换行都不会产生影响。比较的只有实际数据。

工具能比较带注释或尾随逗号的 JSON 吗? 不能。RFC 8259 定义的标准 JSON 不允许注释或尾随逗号。包含这些内容的输入会被判定为无效并拒绝。

参考文献

  1. IETF。《JavaScript 对象表示法(JSON)数据交换格式》。RFC 8259,2017 年 十二月。
  2. IETF。《JavaScript 对象表示法(JSON)补丁》。RFC 6902,2013年4月。
  3. IETF。《JSONPath:JSON 查询表达式》。RFC 9535,2024 年 二月。(第 2.2 节定义了根标识符 $。)
  4. Mozilla Developer Network。《JSON.parse()》。