abox.tools

語言: 繁體中文

怎樣比對兩個 JSON 檔案

兩個 JSON 檔案原樣拿來比對,亮起來的大半什麼都不是:縮排、折行、順序不同的鍵。藥方不是更聰明的比對——是先把兩個檔案過同一個格式化器,讓剩下的只有真差異。兩步都跑在你的瀏覽器裡,而裝著機密的配置檔案就該待在那裡。

開啟文字比對 兩段文字進來,每處差異都被標出來,逐行、逐詞。沒有一個字被貼進別人的伺服器。

以 Markdown 檢視

簡短的答案

  1. 開啟 JSON 格式化,貼入第一個檔案,縮排設成兩個空格,勾上「排序每個物件的鍵」。複製結果。
  2. 開啟文字比對,貼進左邊的框。
  3. 第二個檔案照做,貼進右邊的框。

現在亮起來的是真的:變了的值、冒出來的鍵、消失的條目。會淹死普通比對的格式差異和換了位置的鍵都沒了,因為比對開始之前,兩邊已經寫成了同一種拼法。

兩個頁面都沒有任何網路功能——這一點值得知道:人們拿來比對的 JSON,太多時候是憑據還躺在裡面的配置檔案。

為什麼生比 JSON 幾乎全是噪音

JSON 不在乎空白,也不給鍵的順序賦予意義。同一份文件可以是一行,也可以是四百行;鍵可以按敲下的順序排,也可以按某個庫吐出的順序排——工具改寫這兩樣從不打招呼。一邊壓縮了,一邊鋪開了;一邊手工存的,一邊出自按字母排序的序列化器:逐行比對看見的是兩個不相干的檔案。

兩個最糟的情形足以說明問題。壓縮過的檔案是一行,於是和它比對得到一條巨大無比的變更行——正確,且無用。而內容相同、順序不同的兩個檔案會比出個處處皆變,誠實的答案本該是「什麼都沒變」。

比較選項:並排或單欄檢視、只顯示改動行的開關,以及忽略空白、忽略大小寫、忽略空行的開關。
正是它們,讓一份檔案只因為換行符不同就被報成整篇都改了的事不再發生。

格式化器的規範形修好了什麼

兩個檔案過同一個格式化器、用同樣的設定,正是比對需要的:一份文件一種拼法。

一句誠實的但書:排序後的輸出是鍵挪了位的文件。要是下游某個工具在乎鍵的順序——在乎的不多,但存在——就把排序的副本當作被比對的東西,而不是原件的替身。

讀結果,並帶走它

比對把刪掉的行標在左邊、新增的行標在右邊,變了的行裡再把不同的詞高亮出來:在規範形上,那通常就是從 false 挪到 true 的那一個值。沒變的中段摺疊成一個數字,兩千行的配置改了三處,讀起來就是三小段。

下載下來的是統一格式的補丁,一個 .patch——程式碼評審看得懂的格式。它描述的是規範形,而那通常正是評審想要的:只有改動,沒有重排。

同一套做法對兩個頁面會說的其他東西同樣有效。YAML 和 XML 用同樣的方法化成規範形;來源不同、形狀相同的兩個檔案,比對的忽略開關——空白、大小寫、空行——就是同一想法的輕量版。

同一份 JSON 配置的兩個版本並排顯示,改動過的行都有標記:版本號、重試次數、新增的開關和新增的地區。
四處真正的差異,別的什麼也沒報。讀是容易的那一半,活是上面那些設定乾的。

如果你每週都做這件事

格式化兩次、貼上兩次:步驟住在兩個頁面上,因為每頁只做一件事,而且各自都能證明你貼的東西哪裡也沒去。但兩個都是開源的:MIT 許可證,零依賴的 ES 模組——格式化器的解析器保住鍵序和數位,比對是 Myers 演算法——各配一份講明白它的 README。

要是這已是你每天的一部分,把編碼智慧體指向程式碼儲存庫,請它做一頁兩個框、邊比對邊規範化的頁面:parseJson、printJson 和 compareText 只隔三個 import。這些模組寫出來就是給人讀的,把它們搬走,正是這份許可證存在的目的。