JSONドキュメントの深い等価性チェック

JSON diffツールがフォーマット、キーの順序、空白の違いにもかかわらず、2つのドキュメントが意味的に同一であるかどうかを判定する深い等価性チェックの方法を学びます。

Type & Value Edge Cases

詳細な説明

深い等価性とは、2つのJSONドキュメントが、すべてのネストレベルで完全に同じデータ構造と同じ値を表すことを意味します。深い等価性チェックはJSON diffの基盤です:2つのドキュメントが深く等しい場合、diffは空になります。

深い等価性が無視するもの:

  1. キーの順序: {"a":1,"b":2}{"b":2,"a":1} はJSONオブジェクトが順序なしであるため深く等しいです。
  2. 空白とフォーマット: 圧縮版と整形版の同じデータは深く等しいです。
  3. 末尾のカンマ/コメント: これらは有効なJSONではありませんが、パーサーが比較前にそれらを除去する場合、結果の構造は深く等しい可能性があります。

深い等価性がチェックするもの:

  1. 型が一致する必要がある: "42"(文字列)と 42(数値)は深く等しくありません。
  2. 値が正確に一致する必要がある: 3.143.140 は深く等しい(同じIEEE 754値)ですが、3.143.14159 は等しくありません。
  3. 配列の順序が重要: [1, 2, 3][3, 2, 1] は配列が順序付きであるため深く等しくありません。
  4. nullと欠落の区別: { "a": null }{} は深く等しくありません。
// ドキュメントA
{
  "users": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ],
  "count": 2
}

// ドキュメントB
{
  "count": 2,
  "users": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ]
}

この2つのドキュメントは、ルートレベルでキーの順序が異なるにもかかわらず深く等しいです。配列の内容は同じ順序であるため、それらも等しいです。

JavaScriptでの実装:

JavaScriptの === 演算子はオブジェクトの参照を比較するため、{a:1} === {a:1}false です。深い等価性には再帰的な比較関数が必要です。Lodash(_.isEqual)やカスタム実装が一般的に使用されます。JSON.stringify() のトリック(両方を文字列化して文字列を比較)は、キーの順序が同じことが保証されている場合にのみ機能します。

パフォーマンス:

深い等価性チェックはO(n)です(nはドキュメント内のノードの総数)。数百万のキーを持つドキュメントの場合、完全な比較を行う前にサブツリーをハッシュ化して不等価を迅速に検出することを検討してください。

ユースケース

テスト実行間でキーの順序が変わる可能性があるAPIレスポンスが、期待されるJSONフィクスチャと構造的に同一であることを検証する自動テストの作成。

試してみる — JSON Diff

フルツールを開く