简短的答案
现在亮起来的是真的:变了的值、冒出来的键、消失的条目。会淹死普通比对的格式差异和换了位置的键都没了,因为比对开始之前,两边已经写成了同一种拼法。
两个页面都没有任何网络功能——这一点值得知道:人们拿来比对的 JSON,太多时候是凭据还躺在里面的配置文件。
为什么生比 JSON 几乎全是噪音
JSON 不在乎空白,也不给键的顺序赋予意义。同一份文档可以是一行,也可以是四百行;键可以按敲下的顺序排,也可以按某个库吐出的顺序排——工具改写这两样从不打招呼。一边压缩了,一边铺开了;一边手工存的,一边出自按字母排序的序列化器:逐行比对看见的是两个不相干的文件。
两个最糟的情形足以说明问题。压缩过的文件是一行,于是和它比对得到一条巨大无比的变更行——正确,且无用。而内容相同、顺序不同的两个文件会比出个处处皆变,诚实的答案本该是“什么都没变”。
格式化器的规范形修好了什么
两个文件过同一个格式化器、用同样的设置,正是比对需要的:一份文档一种拼法。
- 同样的缩进让每个键各占一行:比对于是逐行工作,它的逐词标记也能指着一行里唯一变了的那个值。
- 排好序的键让两边同序,顺序就不再是差异。排序按键读起来的样子,不按码位——
item2排在item10前——并且两边施加得一模一样。 - 其余分毫不动。这个格式化器让数字保持你写下的每一位,保留重复的键而不是替你裁决:规范化自己变不出差异来。格式化器指南解释了这为什么比理应的更稀罕。
一句诚实的但书:排序后的输出是键挪了位的文档。要是下游某个工具在乎键的顺序——在乎的不多,但存在——就把排序的副本当作被比对的东西,而不是原件的替身。
读结果,并带走它
比对把删掉的行标在左边、新增的行标在右边,变了的行里再把不同的词高亮出来:在规范形上,那通常就是从 false 挪到 true 的那一个值。没变的中段折叠成一个数字,两千行的配置改了三处,读起来就是三小段。
下载下来的是统一格式的补丁,一个 .patch——代码评审看得懂的格式。它描述的是规范形,而那通常正是评审想要的:只有改动,没有重排。
同一套做法对两个页面会说的其他东西同样有效。YAML 和 XML 用同样的路子化成规范形;来源不同、形状相同的两个文件,比对的忽略开关——空白、大小写、空行——就是同一想法的轻量版。
如果你每周都做这件事
格式化两次、粘贴两次:步骤住在两个页面上,因为每页只干一件事,而且各自都能证明你贴的东西哪儿也没去。但两个都是开源的:MIT 许可证,零依赖的 ES 模块——格式化器的解析器保住键序和数位,比对是 Myers 算法——各配一份讲明白它的 README。
要是这已是你每天的一部分,把编码智能体指向代码仓库,请它做一页两个框、边比对边规范化的页面:parseJson、printJson 和 compareText 只隔三个 import。这些模块写出来就是给人读的,把它们搬走,正是这份许可证存在的目的。