1. ホーム
  2. json

[解決済み] JSONファイルを比較するためにjqまたは他のコマンドラインツールを使用すること

2022-03-11 10:08:44

質問

2つのJSONファイルが、辞書のキーとリスト要素の順序に影響を受けずに同一であるかどうかを確認するために使用できるコマンドライン・ユーティリティはありますか?

を使用して行うことができます。 jq または同等のツールはありますか?

これら2つのJSONファイルは同一です

A :

{
  "People": ["John", "Bryan"],
  "City": "Boston",
  "State": "MA"
}

B :

{
  "People": ["Bryan", "John"],
  "State": "MA",
  "City": "Boston"
}

が、この2つのJSONファイルは異なるものです。

A :

{
  "People": ["John", "Bryan", "Carla"],
  "City": "Boston",
  "State": "MA"
}

C :

{
  "People": ["Bryan", "John"],
  "State": "MA",
  "City": "Boston"
}

ということになる。

$ some_diff_command A.json B.json

$ some_diff_command A.json C.json
The files are not structurally identical

解決方法は?

jqの比較はすでにキーの順序を考慮せずにオブジェクトを比較しているので、あとは比較する前にオブジェクト内のすべてのリストをソートすればよいのです。2つのファイルの名前が a.jsonb.json は、最新のjq nightlyで。

jq --argfile a a.json --argfile b b.json -n '($a | (.. | arrays) |= sort) as $a | ($b | (.. | arrays) |= sort) as $b | $a == $b'

このプログラムは、要求された等式の定義を使って、オブジェクトが等しいかどうかによって、"true" または "false" を返す必要があります。

編集 (.. | arrays) |= sort の構成は、実際にはいくつかのエッジケースで期待通りに動作しません。 このGitHubの課題 は、その理由を説明し、いくつかの代替案を提供しています。

def post_recurse(f): def r: (f | select(. != null) | r), .; r; def post_recurse: post_recurse(.[]?); (post_recurse | arrays) |= sort

上記のjqの呼び出しに適用される。

jq --argfile a a.json --argfile b b.json -n 'def post_recurse(f): def r: (f | select(. != null) | r), .; r; def post_recurse: post_recurse(.[]?); ($a | (post_recurse | arrays) |= sort) as $a | ($b | (post_recurse | arrays) |= sort) as $b | $a == $b'