JSON 差分

2 つの JSON 文書を行単位ではなく構造で比較します。追加・削除・変更されたパスを報告し、配列の順序を無視するオプションも用意。処理はすべてブラウザ内で完結します。

行ではなく構造で比較する。 2 つの文書を貼り付けると、何が追加・削除・変更されたかをパス単位で報告します。パース済みの値をたどって比較するため、整形のし直しやキーの並べ替えは差分として現れません。

差分

テキスト差分が JSON に向かない理由

行差分が見ているのは書式であって意味ではない

一般的な行単位の差分は JSON を文章として扱います。インデントを 2 スペースから 4 スペースに変えれば全行が変更扱いになり、キーをオブジェクトの先頭から末尾へ移せば、パース後の値が完全に同じでも削除 1 件と追加 1 件になります。長い配列を 1 行にまとめれば、そのブロック全体が光ります。

構造差分はまず両側をパースし、得られた値をたどって比較します。比較を始める時点で書式・キー順・空白は消えているため、報告されうるのはデータそのものの本当の違いだけです。だからこそ出力が実際に読み切れる長さに収まります。

行番号ではなくパス

ここでの各差分は user.roles[2]meta.updated のようなパスに対して報告されます。行番号と違い、パスは文書の別の場所を編集しても失効しません。そのため同じ報告をチケットやコードレビューに貼っても、1 週間後も正しい箇所を指し続けます。

3 つの操作は、ツリーに起こりうることにそのまま対応します。左にあって右にないキーは削除、その逆は追加、両方にあって値が違うキーは変更です。型の変化——数値の 1 だったフィールドが文字列の "1" になった場合など——も変更として報告されます。これは注視する価値があります。スキーマ検証をすり抜けて下流の不具合を生む典型的な原因だからです。

配列と順序の問題

構造差分で判断が分かれるのが配列です。既定では位置による比較を行い、左のインデックス 0 と右のインデックス 0 を突き合わせます。手順の並びのような順序付きデータには正しい挙動ですが、実質的に集合であるリストでは誤解を招きます。要素を並べ替えただけで、すべての位置が変わったように見えてしまうからです。

「配列の順序を無視」を有効にすると、比較前に両側の配列を再帰的にソートして正規化するため、並べ替えただけのリストは等しいと判定されます。タグ一覧、権限の集合、順序が保証されないクエリ結果にはこちらが適しています。逆に要素の位置に意味がある場合は必ず無効にしてください。有効なままだと、本物の並び順のバグが完全に見えなくなります。

オープンソースに関する注記:バニラ JavaScript で実装。サードパーティライブラリは使用していません。

よくある質問

通常のテキスト差分と何が違いますか?
テキスト差分は行を比較するため、インデントの変更やキーの並べ替えも変更として現れます。本ツールは先に両側をパースするので、データ上の本当の違いだけを報告します。
+、-、~ の記号は何を意味しますか?
プラスは変更後にのみ存在するパス、マイナスは変更前にのみ存在するパス、チルダは両方に存在するが値が異なるパスを表します。
並べ替えただけの配列が変更と報告されるのはなぜですか?
既定では配列を位置ごとに比較しており、順序付きデータにはこれが正しい挙動です。順序なしの集合として比較したい場合は「配列の順序を無視」を有効にしてください。
オブジェクト内のキーの順序は影響しますか?
しません。オブジェクトはキー単位で比較するため、オブジェクト内でフィールドを移動しても差分にはなりません。順序が影響するのは配列要素の位置だけです。
数値が文字列に変わった場合も検出されますか?
されます。型の変化は変更として報告します。これは意図的な設計で、1 と "1" は下流での振る舞いが大きく異なり、見落としやすいためです。
文書はサーバーに送信されますか?
されません。両側の解析と比較はブラウザ内で完結し、アップロードもログ記録も保存も行いません。