JSON 对比工具 做的是语义级 diff——把两份 JSON 解析成结构化值后再比较,忽略 key 顺序、缩进、空白等文本层面的无关差异,只呈现真正的数据改动:新增、删除、修改、数组内移动。
和文本 diff 的本质差别:
| 对比维度 | 文本 diff | JSON 语义 diff |
|---|---|---|
| 比较对象 | 字符序列 | 解析后的值树 |
| key 顺序变化 | 显示差异 | 忽略 |
| 缩进/空白变化 | 显示差异 | 忽略 |
| 数组元素移动 | 显示成删+加 | 识别为 move |
| 适用场景 | 纯文本、代码 | JSON 数据、配置、API 响应 |
四类变更:
id / key / name / uuid 或值指纹识别身份)表达式栏支持 JSONPath ($.data.items[*].id) 和 JS 表达式 (.filter(x=>x.status==='active')),同一表达式同时作用于两侧,适合只对比一部分——例如接口返回了一大堆元数据,只想比 data.items,写 $.data.items 即可。JS 在 Web Worker 里带 1.5 秒超时运行,不会卡住页面。
delta 复制把差异压成 jsondiffpatch 紧凑格式,可以直接作为版本补丁存数据库或传输,点击工具条里 复制 delta 旁的 ? 查看完整格式规范。
什么时候该用文本对比而不是 JSON 对比:关心原始字符串格式(缩进策略、字段顺序、尾逗号)时;输入不是合法 JSON (比如 JSON5、JSONL、片段);或者对比的是非 JSON 文本。反之只要是合法 JSON 且只关心数据变化,JSON 对比视图更清爽。
因为本工具做的是语义 diff——比较 JSON 值本身,而不是字符串。`{"a":1,"b":2}` 和 `{"b":2,"a":1}` 在 JSON 规范里是等价对象,key 顺序不具语义。如果要逐字符对比(比如关心原始序列化格式),请改用 文本对比。
底层用 `jsondiffpatch` 的 `objectHash` 认元素身份:优先看 `id`、`key`、`name`、`uuid` 字段,都没有就 `JSON.stringify` 整个值当指纹。同一元素在两侧位置不同即判为「移动」。推论:原始类型数组(`[1,2,3]` / `["a","b"]`)可以精准识别移动;对象数组若无 id 类字段,改了任意字段就被视为「不同元素」,可能误判成「删除+新增」。
delta 是 jsondiffpatch 的差异 JSON 格式——两份 JSON 的所有改动压成一个紧凑对象,可以存数据库做版本追踪、或在前后端之间只传差异而不是整个对象。叶子节点用数组表示:`[新值]` 新增、`[旧, 新]` 修改、`[旧, 0, 0]` 删除、`["", 新索引, 3]` 数组内移动。用 `jsondiffpatch.patch(left, delta)` 可从左侧还原右侧。工具条里有完整的格式说明弹窗。
JSONPath(以 `$` 开头):`$.user.name`、`$.items[*].id`、`$..price`,选路径、全部命中结果返回数组(单命中自动解包)。JS:`.map(x=>x.id)`、`.filter(x=>x.age>18)`、`.reduce(...)`,把整份 JSON 当作 `data` 变量,走 `new Function`、在 Web Worker 里带 1.5s 超时跑;也可以直接写 `data.user.name`。同一表达式同时应用到两侧,便于只对比关心的部分;点「还原原文」退出表达式视图。
当两侧同一路径的字符串值都比较长(默认阈值很高,工具里已设为 `9999` 基本禁用)时,jsondiffpatch 会调用内部文本 diff 给出字符级补丁而不是 `[旧, 新]` 两值。本工具默认禁用文本 diff(阈值很大)以保证 delta 易读;如果看到「字符串差异」,说明某些场景仍触发了——直接看编辑器里的高亮行即可。
是的——左右都是完整 Monaco 编辑器,粘贴、修改都会在 300ms 防抖后自动重新对比,无需手动点按钮。`Alt+↑` / `Alt+↓`(或 `Alt+k` / `Alt+j`)切换差异;点差异树条目跳转编辑器对应行并闪烁提示。输入内容自动持久化到浏览器本地,刷新不丢。
jsondiffpatch 自定义的差异 JSON 格式——把两份 JSON 的所有改动压成一个紧凑对象。
可以存数据库做版本追踪、用 jsondiffpatch.patch(left, delta) 反向还原右侧、或在前后端之间只传差异而非完整对象。
[新值][旧值, 新值][旧值, 0, 0](末尾双 0 是删除标记)[diff 字符串, 0, 2](长字符串才触发,当前工具已禁用)["", 新索引, 3] 0=删除,2=文本 diff,3=移动。{ "name": "Alice", "age": 30 }{ "age": 30 }{ "name": ["Alice", 0, 0] }["a", "b", "c"] → 右:["a", "c"]{ "_t": "a", "_1": ["b", 0, 0] }_t: "a" 标记数组 delta;键名带 _ 前缀表示「原数组的索引」(下划线 1 = 旧索引 1 被删)。$.a.b[0] 的改动会嵌在 { a: { b: { _t:"a", "0": ... } } } 里。