ゆるテックノート

JSONの差分は、行の違いより値の違いを見る

設定ファイルを整形し直しただけなのに、差分が画面いっぱいに出る。逆に、よく似たAPIレスポンスのどこが変わったのか見つからない。そんなときは、文字列としての比較と、JSONの構造を読んでからの比較を使い分けると追いやすくなります。

オブジェクトのキー順が変わっても、対応する値は同じ

オブジェクトは名前と値の組です。RFC 8259では順序を持たない集合として定義されます。次の二つは文字の並びが違いますが、nameとcountに対応する値は同じです。Online ToolsのJSON差分比較でも差分なしになります。

キー順だけを入れ替える例

上は変更前、下は変更後として別々の入力欄へ貼り付けます。二つを連結したまま一つのJSON文書として渡すとエラーになります。空白や改行の量も構造の比較では差分になりません。署名やファイルのハッシュを比べる場合は元のバイト列が関わるため、この意味での一致とは別です。

{"name":"sample","count":2}

{"count":2,"name":"sample"}

配列の並び順は値の一部

一方、配列には順序があります。ランキングや処理手順なら、同じ要素が入っていても並び替えで意味が変わります。このツールは配列を位置で比較するため、要素の移動を自動で追跡するものではありません。

先頭に一つ足すと後ろにも差分が出る

人には「greenを先頭に挿入した」と見えても、位置比較ではこうなります。IDで同一の要素を追いたい一覧なら、IDを使う比較方法を別に選びます。配列を先にソートすると順序の変更を消してしまうため、順序が意味を持たないと決まっている場合だけにします。

{"items":["red","blue"]}

{"items":["green","red","blue"]}
path 判定 変更前 → 変更後
/items/0 changed "red" → "green"
/items/1 changed "blue" → "red"
/items/2 added なし → "blue"

pathは変更された値までの道順

結果のpathはRFC 6901のJSON Pointerです。スラッシュで階層を進み、配列の先頭は0で表します。キー自体にスラッシュやチルダがある場合は、区切りと混ざらないよう別の表記になります。

記号を含むキーを読む

/と空文字列は別です。また、ここで使う~1はURLの%2Fとは別のエスケープです。JSON PointerをURLのフラグメントに載せる場合には、さらにURI用の表記規則が関わります。

path 指す場所
空文字列 文書全体
/items/0 items配列の先頭
/a~1b a/bという名前のキー
/m~0n m~nという名前のキー
/ 空文字列を名前にしたキー

1と1.0は同じ数値、文字列の1は別

このツールは数値を通常のJavaScript Numberへ丸めず、入力された数値トークンから比較します。1・1.0・1e0は一致し、大きな整数の末尾が違えば変更として出ます。これは本ツールの数値比較方針であり、JSONの見た目を完全にそろえる機能ではありません。

型と精度を分けた結果

先に通常のJSON整形へ通すと、大きな整数の違いが丸めによって消える場合があります。精度を調べる比較では、取得した元のテキストを左右に入れます。

変更前 変更後 本ツールの結果
{"n":1} {"n":1.0} 差分なし
{"n":1} {"n":"1"} /n がchanged
{"id":9007199254740992} {"id":9007199254740993} /id がchanged

差分の一覧は、そのまま適用するパッチではない

added・removed・changedは、このツールの結果表示です。JSON Patchのop・path・valueを持つ更新命令とは形式が違うので、結果をそのままAPIへ送って更新する用途には使えません。差分を見た後は、対象アプリの設定方法や更新APIに合わせて変更します。

比較が止まるとき

重複キーは、どちらの値を比べるか曖昧になるためエラーになります。入力は左右それぞれ50万文字、入れ子100段、差分1万件までです。大きなデータは関連する項目ごとに分けると、限界を避けるだけでなく変更理由も読み取りやすくなります。

キー順と配列順を一つずつ試す

JSON差分比較ツールに、まずキー順だけを入れ替えた例を入れ、次に配列の例を入れると判定の違いがわかります。行順が変わる表データには、ID列で対応を取るCSV差分比較も使えます。

関連記事と仕様

読み込みエラーや丸めはJSONの構文エラーと数値精度へ。構造の定義はRFC 8259 §1、pathはRFC 6901 §§3–4、更新命令としてのJSON PatchはRFC 6902 §4が根拠です。