JSON比較ツール

2つのJSONオブジェクトを比較して、強調表示された違いを視覚化します。

データはデバイスを離れません

JSON比較について

JSON比較(JSON差分とも呼ばれる)は、2つのJSON構造間の違いを識別します。プレーンテキストの差分とは異なり、JSONを理解する比較は、キーと値を認識し、キーの順序に関係なく、どのプロパティが追加、削除、または変更されたかを正確に伝えることができます。

このツールは、2つのJSONオブジェクトの深い再帰的比較を実行します。ネストされたオブジェクト、配列、文字列、数値、ブール値、null値を処理します。すべての処理はブラウザ内でローカルに行われます。

JSONの簡単な歴史

JSONの伝記は平均的なプログラミング言語よりも短く、はるかにドラマチックではありません。頭字語はState Software, Inc.で生まれました。Douglas CrockfordとChip Morningstarが2001年3月に設立した小さな会社で、後にAjaxウェブアプリケーションと呼ばれるものを構築するためでした。最初のJSONメッセージは2001年4月にMorningstarのベイエリアのガレージにあるコンピューターから送信されました。CrockfordはJSONを発明したと主張しません、彼はJavaScriptのオブジェクトリテラル構文から剥がし、名前を付け、ウェブサイトを立ち上げました。彼は2002年にjson.orgを取得し、そこに鉄道図文法を投稿しました。4年間、JSONは口コミとライブラリ実装のゆっくりとした流れで広がりました。2005年12月、Yahoo!は一部のウェブサービスをJSONで提供し始め、ほとんどの歴史家がJSONがメインストリームに渡った瞬間と指摘する瞬間です。標準化は波で来ました: RFC 4627(2006年7月)、Crockford自身によって書かれ、標準トラックではなく情報的なステータス; ECMA-404第1版(2013年10月); RFC 7159(2014年3月)、JSONをIETF標準トラックに置き、トップレベル値がオブジェクトまたは配列であるという要件を緩和しました。現在のバージョンはRFC 8259(2017年12月)、現在Internet Standard STD 90、およびECMA-404第2版(2017年12月)です。2つは意図的に文法的に同一です; IETFテキストはEcmaテキストが意図的に省略するセキュリティと相互運用性のガイダンスを追加します。

2つのアルゴリズム的ファミリー: ラインdiffと構造的diff

コンピュータサイエンスは1970年代からdiffingについて考えてきました。Douglas McIlroy(Unixパイプを発明した同じMcIlroy)とJames W. Huntは1970年代初頭にオリジナルのUnix diffを書きました; これは1974年のUnix第5版の一部として出荷され、基盤となるアルゴリズムは1976年6月のBell Labs Computing Science Technical Report #41で文書化されました。Hunt-McIlroyは最長共通部分列問題に基づいて構築されています。両方の入力に順番に現れる最長の行のシーケンスを見つけ、そのシーケンスにないものはすべて削除または挿入のいずれかです。10年後、Eugene W. MyersAlgorithmica第1巻第2号(1986)で「An O(ND) Difference Algorithm and Its Variations」を発表し、問題を「edit graph」上の最短経路探索として再構成しました。これは、前任者より2〜4倍速く実行されたより高速なUnix diff実装の基礎です。今日、git diffはLibXDiffのhistogramアルゴリズムをデフォルトとし、バニラMyersよりも一般的に速く、特に移動されたブロックの周りでより読みやすい出力を生成します。Patience diff(Bram Cohen、2008)は、ユニークなアンカー行に優先順位を付ける別のLCS改良です。すべてテーマのバリエーション: 行ごとのLCS、入力を不透明なトークンのフラットなシーケンスとして扱います。誰もJSONが何であるかを知りません。

構造的diffファミリーは異なるアプローチを取ります: 両方の入力を並行して歩き、プリミティブを厳密な等価性で比較し、オブジェクトキーの結合を計算し(左にのみ存在するものは「削除」、右にのみ存在するものは「追加」、両方に存在するものは再帰を意味する)、配列をインデックスごとに歩きます。各位置で、再帰します。1つの配列が長い場合、追加要素が追加または削除されます。型の変更(数値対文字列、オブジェクト対配列)は「型変更」エントリになります。これはjsondiffpatchがベースケースとして実装するアルゴリズムであり、このツールが実装するアルゴリズムです。その強みは出力が意味のあることです: 報告されるすべての変更にはドキュメント内のパス(user.address.cityitems[3].price)と明確なセマンティクスがあります。その弱点は3番目のステップ、インデックスによる配列の比較で、要素が長い配列の先頭近くに挿入されるたびにナンセンスを生成します。

JSON diffingで最も難しい問題: 配列

「before」JSONに配列 ["alpha", "beta", "gamma", "delta"] が含まれ、「after」JSONに ["alpha", "new", "beta", "gamma", "delta"] が含まれているとします。素朴なインデックスベースのdiffは4つの変更を報告します: インデックス1は「beta」から「new」に変更; インデックス2は「gamma」から「beta」に変更; インデックス3は「delta」から「gamma」に変更; インデックス4は「delta」を追加。これを見ている人間は、変更は1つあると言います: インデックス1での1つの挿入です。これは、テキスト行の配列ではなくJSON値の配列に適用された、ライン-diffファミリーが1970年代に解決したのと同じLCS問題です。jsondiffpatchはまさにそれを行います、2つの配列のLCSを計算し、それに対する挿入と削除を発行します。プリミティブの配列ではこれはうまく機能します。オブジェクトの配列ではそうではありません: [{id: 1, name: "Alice"}][{id: 1, name: "Alicia"}] は参照等価性による共通部分列を持たないため、素朴なLCSは「左の要素全体を削除、右の要素全体を追加」と報告します。真実は1つの要素の1つのフィールドが変更されたことです。jsondiffpatchの解決策はobjectHashコールバックです: 呼び出し元は各オブジェクトを識別キーにマップする関数を提供し(通常 obj => obj.id)、diffは参照ではなく識別によって配列要素をマッチさせます。これは誰も完全に解決していない難しい一般的な問題です。Absolutoolツールは、独自のFAQによれば、配列をインデックスで比較し、LCSやobjectHashを実装しません。これは小さな無料ツールの意図的な範囲選択です: オブジェクトのdiffに優れ、要素が挿入または並べ替えられた配列で弱いです。

JSON Patch (RFC 6902): 転送形式としてのdiff

RFC 6902、「JavaScript Object Notation (JSON) Patch,」は2013年4月に公開されました。メディアタイプ application/json-patch+json と6つの操作のパッチ言語を定義します: add、remove、replace、move、copy、test。パッチ自体はJSONドキュメントで、操作オブジェクトの配列で、それぞれ op キー、path キー(ターゲット位置へのJSON Pointer)、および必要に応じて値または from フィールドを持ちます。操作は順番に、アトミックに適用されます: いずれかが失敗した場合、パッチ全体が拒否されます。パスの構文はRFC 6901、「JSON Pointer,」から来ています。これは同じ月に公開されたコンパニオンドキュメントで、スラッシュ区切りの参照トークンの小さな文字列構文です(/user/address/city は「user内のaddress内のキーcityの値」を意味します; /items/3 は「itemsの4番目の要素」を意味し、ゼロインデックス)。/~ は特別なので、それぞれ ~1~0 にエスケープされます(その順序で、二重デコードバグを避けるために最初に ~1 をデコード)。JSON Patchは、結果を別のマシンに供給したいJSON diffツールに適した出力形式です。HTTP PATCH メソッド(RFC 5789)は、まさにこの種の部分更新ペイロードのために設計されました。Kubernetesは独自のstrategic-merge-patch形式と並んでRFC 6902をサポートします。このツールは現在JSON Patchを出力しません、それは将来の機能方向であり、現在のものではありません。

JSON Merge Patch (RFC 7396): よりシンプルでロッシーな代替手段

RFC 7396、「JSON Merge Patch,」は2014年10月にPaul HoffmanとJames Snellによって公開されました。それは操作をまったく使用しません、パッチドキュメントは単に元の上にオーバーレイされる部分的なJSONオブジェクトです。パッチに存在するフィールドは元の対応するフィールドを上書きします; パッチで null に設定されたフィールドはそのフィールドを削除します; パッチに存在しないフィールドは変更されません; 配列は全体として置き換えられ、決してマージされません。Merge Patchは簡潔で手で書きやすいです。トレードオフは表現力の喪失です: フィールドの値をリテラルの null に設定する方法がない(null は「削除」を意味するため); 配列の単一要素を変更する方法がない(配列全体が置き換えられる); 移動またはコピーを表現する方法がない; 「このフィールドに触れていない」と「現在の値に設定したい」を区別する方法がない。ほとんどの日常的なAPI更新ではこれらの制限は許容範囲です。これがMerge Patchが2つの形式のうちより人気がある理由です。RFC 6902はいずれかの制限が噛むシナリオで勝ちます。Kubernetesは両方の形式を意図的に使用し、各コンテキストに適したものを選択します。

ビジュアルdiffがどのようにレンダリングされるか

構造的diffを表示するための3つの一般的な視覚的慣習があります。サイドバイサイド、2つのカラム、左に元、右に変更後、対応する行が整列されています(このツールが入力に使用するレイアウト)。インライン統一diff、削除された行(通常 - でプレフィックスされ、赤で色付けされている)、追加された行(+、緑)、および変更されていないコンテキスト行(プレフィックスなし、プレーンテキスト)を表示する単一カラム、git diff がデフォルトで使用するレイアウト。ツリービュー、JSONを折りたたみ可能なツリーとしてレンダリングし、変更されたノードを強調表示し、変更されていないノードを折りたたみます。色の慣習はエコシステム全体で著しく一貫しています: 追加には緑、削除には赤、変更された値には黄色または琥珀色、変更されていないものには中立的なグレー。このツールは慣習に正確に従います: 追加にはライトグリーン、削除にはライトレッド、変更にはライトイエロー。ほとんどのユーザーはGitHub、GitLab、BitBucket、すべてのIDE diffビュー、数十のオンラインツールから色を認識します。

一般的な用途

知っておく価値のあるエッジケース

数値精度。 RFC 8259はJSON数値が任意精度であり、数値が持てる桁数に上限を設けないと言っています。しかしJavaScriptは、すべての数値を64ビットIEEE 754 doubleとして解析します。Number.MAX_SAFE_INTEGER(253 − 1 = 9,007,199,254,740,991)を超えると、整数はJavaScriptベースのdiffを通してラウンドトリップする際に静かに精度を失う可能性があります。同じ問題は浮動小数点に影響します、0.1 + 0.2 は IEEE 754 で 0.3 と正確に等しくないことで有名です。厳密なJSONはまた、末尾のカンマとコメントを許可しません; 両方ともRFC 8259による構文エラーです。JSON5(json5.org)はコメント、末尾のカンマ、シングルクォート、引用符なしのキー、16進数、前後の小数点、Infinity/NaNを許可する正式なスーパーセットです。JSONCはVS Codeの設定ファイルで使用されるMicrosoftの「コメント付きJSON」モードです。このツールは JSON.parse() を使用するため、両方を拒否します、貼り付ける前にコメントと末尾のカンマを取り除いてください。

日付文字列。 JSONにはネイティブ日付型はありません。日付は通常、文字列としてエンコードされ、デファクト標準はISO 8601(具体的にはほとんどのインターネットAPIが使用するRFC 3339プロファイル): YYYY-MM-DDTHH:MM:SS[.fff]Z。日付を文字列として比較するdiffは、文字列が異なるため、同じ瞬間を表すにもかかわらず、2024-01-01T00:00:00Z2024-01-01T00:00:00.000Z を異なるものとして報告します。重複キー。 RFC 8259 §4 は「オブジェクト内の名前は一意であるべきです」と述べており、SHOULDは規範的にMUSTよりも弱いです。JavaScriptの JSON.parse() は重複キーを受け入れ、静かに最後のものを保持します; 他のパーサーは最初のものを保持するかエラーを発生させる可能性があります。null対欠落。 {"a": null}{} は異なるJSON値です。このツールは最初のものを「キー a の値はnull」、2番目のものを「キー a がない」と報告し、正しく区別されます。JSON Merge Patchが null を削除シグナルとして扱うのは、区別が実在し、扱いにくいというフォーマットレベルの認識です。

2026年のエコシステム

オープンソースのJSON diffは少数のライブラリによって支配されています。jsondiffpatchはBenjamin Eidelmanによる、2012年に最初に公開された、デファクトJavaScriptライブラリ: ~5kのGitHubスター、objectHash、LCS配列、逆パッチ、ビジュアルHTMLフォーマッタをサポート。json-diffはAndrey Tarantsovによる正典的なNode CLIツールで、Python、Go、Rustの並行実装が同じ名前を共有しています。DeepDiffはSep Dehpourによる支配的なPythonライブラリで、順序を無視するオプション、数値型変更を無視するオプション、および多数の細かい制御を持つ再帰diffです。Linux FoundationのJsonNodeのJackson(Java)でのdiffingは標準JVM選択肢です。jqにはネイティブのdiffコマンドはありませんが、=// 演算子ファミリーは単純な構造比較を表現できます。VS Code組み込みdiffはテキストモードでJSONを処理します; JSON Tools拡張機能はJSON対応の比較を追加します。Diffcheckerのようなオンラインツールは、このツールが実装する本質的に同じ再帰ウォークを提供するJSONモードを提供し、しばしば同じライブラリの上に層化されています。

なぜブラウザのみがここで重要なのか

サーバー上で2つのJSONペイロードのdiffを取ることは、両方をアップロードすることを必要とします。通常の公開データの例ではこれは無害です。認証トークン、顧客PII、内部従業員レコード、構成秘密、未リリースの製品データを含むAPIレスポンスでは、そうではありません。diffが終了した後でも、それらのペイロードはサーバーログ、おそらくCDNキャッシュ、おそらく分析パイプライン、おそらくバックアップに残ります。ブラウザのみのdiffは決して送信しません、JSONは完全にあなたのタブで解析され、ウォークされます。Compareをクリックする間にDevToolsのネットワークタブを開くことで検証できます; 送信リクエストはありません。APIレスポンスをベースラインと比較する、環境間の構成ドリフトをデバッグする、または内部パッケージURLを含むロックファイルの変更を監査するには、「JSONは私のデバイスを決して離れない」が、ツールを実際の本番データで安全に使用できるアーキテクチャです。

よくある質問

キーの順序は比較に影響しますか?

いいえ。JSONオブジェクトは仕様上順序がないため、{"a":1, "b":2}と{"b":2, "a":1}は同一として扱われます。実際の値の違いのみが報告されます。

配列はどのように比較されますか?

配列はインデックスごとに比較されます。インデックス2の配列が2つの入力間で異なる場合、その特定のインデックスがフラグ付けされます。配列の末尾で追加または削除された要素も検出されます。

深くネストされたオブジェクトはどうなりますか?

比較は完全に再帰的です。任意の深さのネストされたオブジェクトと配列が、プロパティごとに比較されます。出力は各違いの完全なパスを表示します(例: 「user.address.city」)。

なぜ私の大整数比較が間違って見えるのですか?

JavaScriptはすべてのJSON数値を64ビットIEEE 754 doubleとして解析します。Number.MAX_SAFE_INTEGER(253 − 1 = 9,007,199,254,740,991)を超えると、整数は静かに精度を失う可能性があります。したがって、9007199254740993 を含むJSONファイルは、9007199254740992 を含むファイルと同一として比較される可能性があります。これは基盤となる数値表現の制限であり、diffツールではありません。64ビットID(Twitter snowflake ID、Discord ID、大きなデータベースキー)を含むデータをdiffする場合は、シリアライザーに数値の代わりに文字列としてそれらを出力させてください。浮動小数点比較には同じ注意点があります: 0.1 + 0.2 は IEEE 754 で 0.3 と正確に等しくないことで有名です。

JSON5またはJSONC(コメント付きJSON)を比較できますか?

直接はできません。このツールはブラウザの組み込み JSON.parse() を使用しており、これはRFC 8259に厳密に従います、コメント、末尾のカンマ、シングルクォート文字列、引用符なしのキーは構文エラーです。入力がJSON5(json5.org)またはVS CodeスタイルのJSONCの場合、最初にコメントと末尾のカンマを取り除くか、貼り付ける前に jsonc-parser のようなツールで厳密なJSONに変換するために実行します。

私のJSONはサーバーに送信されますか?

いいえ。比較はJavaScriptを介してブラウザ内で完全に実行されます。貼り付けたJSONは決してネットワークを越えません。Compareをクリックする間にDevToolsのネットワークタブで検証するか、ロード後にページをオフラインにしてdiffがまだ機能することを確認します。認証トークン付きAPIレスポンス、秘密を含む構成ファイル、または顧客PIIを含むデータベースエクスポートを比較するのに安全です。

関連ツール