免費且無需註冊的 JSON diff 是一種瀏覽器端的比對工具,會剖析兩個嚴格的 JSON 值、走訪剖析後的結構,並在 RFC 6901 JSON Pointer 路徑上回報每一筆新增、刪除、修改與型別變更的項目,過程中不需要帳號、電子郵件或伺服器上傳。比對發生在你的分頁中,因此你貼上的文件不會離開你的機器。物件成員順序與空白不會產生雜訊,因為這個工具比對的是剖析後的資料而非格式化後的文字,而值、型別、鍵與陣列位置上的真正差異則會顯示出來。路徑指出在哪裡觀察到變更,並不代表某個操作可以被自動套用。其產出是一份以審閱為導向的變更清單,而非 RFC 6902 JSON Patch、JSON Merge Patch、文字 unified diff 或結構描述遷移,因此在使用任何自動套用之前,應該先閱讀這份清單。每一邊可以是任何 JSON 值——物件、陣列、字串、數字、布林值或 null——而每個輸入皆受到字元數、巢狀深度與總輸出大小的限制。

free json diff no sign up
免費 JSON Diff,無需註冊:以瀏覽器優先的工作流程

免費、無需註冊的 JSON Diff 究竟做了什麼

JSON Diff 是一種結構比對工具,而非文字比對工具。它會將兩邊都剖析為嚴格的 JSON,再以確定性的順序走訪剖析後的物件與陣列結構。對於物件,它會忽略來源文字的成員順序、排序成員名稱,然後遞迴比對每個值。對於陣列,它以零起始的位置進行走訪,因此重新排序會以多個差異而非單一語意位移的形式呈現。型別維持不變但值不同的基本型別會被回報為 變更(changed);變成不同 JSON 型別的基本型別——例如數字變成字串、物件變成陣列、null 變成其他東西——會被回報為 型別變更(type-changed)。每個位置都以 RFC 6901 JSON Pointer 表示,因此包含斜線的鍵會變成 ~1,包含波浪號的鍵會變成 ~0。陣列索引是十進位權杖,根以空字串而非前置斜線表示。

這個工具絕不會捏造身分、不會計算最長共同子序列,也不會把陣列視為集合。這些行為仰賴這個工具並不假設存在的資料契約,而且它們可能會隱藏有意義的順序變更。這也是為什麼物件鍵的重新排序不會產生差異:JSON 物件是無序的成員名稱與值集合,而比對也以這種方式處理它們。只在右側出現的鍵視為新增,只在左側出現的鍵視為刪除,兩側都存在的鍵則遞迴比對。

每筆輸出項目都帶有足夠的資訊,讓人類能閱讀,也能複製進票證或程式碼審閱中。新增項目包含右側的值,刪除項目包含左側的值,而變更與型別變更項目則同時包含兩者。當整個成員被新增、刪除或型別變更時,子樹會以值的形式呈現,這讓報告保持精簡,並讓高層次的變更一目了然,而不是把它埋在每一個分葉底下。鍵在回報前會進行排序,因此無論原始文件如何格式化,相同的兩個輸入總是會產生相同的變更清單。

如何在瀏覽器中比對兩個 JSON 文件

三個步驟就能完成整個工作流程。過程中任何時刻都不需要帳號、權杖或 API 金鑰。

  1. 貼上嚴格的左側與右側 JSON 文件。在瀏覽器中開啟 JSON Diff 工具,將原始文件貼在左側、候選文件貼在右側。兩個輸入之間的空白、縮排與物件成員順序可能不同——這是預期中的情況,不會在輸出中產生雜訊。
  2. 比對並檢視每一筆回報項目。執行比對並閱讀產生的變更清單。每一筆項目都會顯示 RFC 6901 路徑、類別(新增、刪除、變更或型別變更),以及涉及的值。根路徑是空的 JSON Pointer,在人類可閱讀的清單中,當整個值變更時會以 root 表示。
  3. 複製變更清單以供審閱。使用複製動作將結構化變更陣列放到剪貼簿,然後貼到審閱文件、Pull Request 描述或對話串中。請勿把這份清單導入自動套用程式:它是一份以審閱為導向的清單,而非 RFC 6902 JSON Patch,也沒有實作 patch 套用語意。

解讀輸出:路徑、型別與變更類別

變更清單簡單且可預期。每筆項目都歸屬於四個類別之一,且類別之間互斥。一旦你知道每個類別的意義,結果讀起來就像變更的目錄。

類別回報欄位出現時機
新增RFC 6901 路徑、右側值某個成員或陣列元素只出現在右側,未出現在左側。
刪除RFC 6901 路徑、左側值某個成員或陣列元素只出現在左側,未出現在右側。
變更RFC 6901 路徑、左側值、右側值兩側同一個路徑的 JSON 型別相同,但純量值不同。
型別變更RFC 6901 路徑、左側值、右側值兩側同一個路徑有不同的 JSON 型別——例如數字變字串,或物件變陣列。

鍵會排序以進行確定性回報,這代表無論原始文件如何格式化,相同的兩個輸入總是會產生相同的變更清單。當整個物件或陣列子樹被新增、刪除或型別變更時,子樹會以值的形式呈現,而非展開為內部每一個分葉的平坦清單。這讓報告保持精簡,並讓高層次的變更一目了然,而不是把它展開成一大面巢狀條目。

嚴格剖析、被拒絕的輸入與限制

兩個輸入都會被剖析為嚴格的 RFC 8259 JSON。註解、尾端逗號、undefined、NaN、Infinity、BigInt 語法與 JavaScript 物件實字會在比對開始前被拒絕。每個輸入可以是任何 JSON 值:物件、陣列、字串、數字、布林值或 null。根是空的 JSON Pointer,而非前置斜線。

三個硬性上限保護比對不會無限制地執行:

  • 每側 500,000 字元。超過的內容會在剖析開始前失敗,這能避免瀏覽器啃下數 GB 的貼上文字。
  • 50 層比對巢狀深度。更深的內容會在剖析時失敗,這能避免遞迴走訪在病態輸入上炸掉呼叫堆疊。
  • 輸出中 5,000 筆變更。如果比對會產生超過 5,000 筆項目,工具會失敗而非悄悄截斷結果,因此你永遠不必猜測你看到的清單是否完整。

JSON 數字會以 JavaScript Number 進行剖析,因此超出安全整數範圍的整數與非常細微的十進位差異,可能在比對執行前就已經被四捨五入。正零與負零會比較為相同的 JSON 數值。JSON 文字中的重複名稱無法作為獨立項目進行比對,因為正常的 JSON 剖析會在工具看到物件對應之前將其合併。如果你的資料契約仰賴精確的十進位拼法、重複名稱或任意精度整數,請使用為該契約設計的剖析器與數值模型來比對來源,而不是依賴瀏覽器端的 JSON 剖析。

為什麼物件鍵的順序不會出現在輸出中

根據規範,JSON 物件是無序集合。來源文字的成員順序不帶語意,因此一個會比較格式化文字的工具,會在某個編輯器重新格式化文件、在底部新增一個鍵,或正規化格式化工具的輸出時,回報出虛假的「差異」。由於這個工具先剖析再比對,它會在每個物件層級先對鍵進行排序,再進行比對,原本的寫入順序會被捨棄。這會產生一份穩定且確定性的報告,與資料實際被定址的方式一致:是依成員名稱,而非依出現順序。

空白也具備同樣的特性。Tab、空格、空行與尾端換行永遠不會進入比對階段,因為嚴格的 JSON 剖析會在走訪開始前將其正規化。任何你在文字型 diff 中會看到的雜訊都會被濾掉,因此進入報告的只有真正的值、型別、鍵與陣列位置差異。

隱私界線:為什麼無需註冊代表本機處理

在此脈絡下,「無需註冊」代表比對是在你的瀏覽器分頁中本機進行。沒有帳號要建立、沒有電子郵件要驗證、沒有 API 金鑰要輪替——而剖析與比對在本機執行,因此沒有遠端端點會收到你的文件。剖析後的 JSON 值停留在頁面中;變更清單在用戶端產生;複製動作把結果放到你的剪貼簿,而不是伺服器。

這個特性改變了你可以安全使用它的工作流程。你可以貼上敏感的設定、內部 API 回應、結構描述檔案與部分匯出,而不會在廠商的日誌中留下軌跡。然而,它並不會讓這個工具在未經他人同意的情況下用於他人的機器,也無法將文件內部的資料匿名化。貼上之前請檢視內容,複製進票證或對話(讓其他人可見)之前請先檢視變更清單。

何時應該改用具備 Patch 功能的專用工具

這份變更清單是為審閱而設計,並非為自動套用而設計。它不會輸出 move、copy 或 test 操作,也不會聲稱某個被刪除的值在周圍變更後能被還原。如果你打算把差異套回左側文件,請使用具備你資料契約實際所需語意的維護良好的 patch 函式庫——以 RFC 6902 定義的操作集合來說用 RFC 6902 JSON Patch;契約是 RFC 7396 時使用 merge patch 函式庫;文件比扁平設定物件更結構化時,則使用應用程式專屬的轉換器。

在大多數日常情境——檢查設定變更是否合理、比對兩個 API 回應、肉眼檢視遷移腳本的結果——以審閱為導向的 diff 正是你想要的東西。路徑清單給你調查的位置,類別告訴你發生了什麼類型的變更,而變更前與變更後的值讓你能判斷這個變更是否為刻意為之。將一份以審閱為導向的清單自動套用是一個獨立的決策,需要自己的工具、自己的測試與自己的回復機制,而把兩者混為一談,正是無聲的資料損毀悄悄溜進管線的方式。

相關閱讀:在 Notepad++ 中無需外掛格式化 JSON。

相關閱讀:如何在不遺失資料的情況下壓縮 JSON 檔案。