jqを使用して2つのファイルから2つのJSONオブジェクトをマージする方法


123

私が使用しているJQの解析JSONにシェルスクリプトの中で(JQ-JSON-プロセッサ)ツール。

2つのjsonファイルがあり、それらを1つの一意のファイルにマージしたい

ここにファイルの内容:

file1

{
    "value1": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2"
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        }
    }
}

file2

{
    "status": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value3": "v3"
        },      
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

期待される結果

{
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        },
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

私はたくさんの組み合わせを試みますが、私が得る唯一の結果は以下です、これは期待された結果ではありません:

{
  "ccc": {
    "value2": "v2",
    "value1": "v1"
  },
  "bbb": {
    "value2": "v2",
    "value1": "v1"
  },
  "aaa": {
    "value2": "v2",
    "value1": "v1"
  }
}
{
  "ddd": {
    "value4": 4,
    "value3": "v3"
  },
  "bbb": {
    "value3": "v3"
  },
  "aaa": {
    "value4": 4,
    "value3": "v3"
  }
}

このコマンドを使用する:

jq -s '.[].value' file1 file2

1
jsontoolを試しましたか?github.com/trentm/json
Nano Taboada

まだ、見てみましょう。Thx
Janfy

でこれを行うにはjson、使用:cat f1 f2 | json --deep-merge
xer0x

どこで/どのようにjson@ xer0x を取得しますか?
Gus

@Gusああ、jsonツールを入手するにはgithub.com/trentm/jsonに
xer0x

回答:


154

1.4以降、これは*オペレーターで可能になりました。2つのオブジェクトを指定すると、それらは再帰的にマージされます。例えば、

jq -s '.[0] * .[1]' file1 file2

重要:-s (--slurp)ファイルを同じ配列に配置するフラグに注意してください。

あなたを得るでしょう:

{
  "value1": 200,
  "timestamp": 1382461861,
  "value": {
    "aaa": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3",
      "value4": 4
    },
    "bbb": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3"
    },
    "ccc": {
      "value1": "v1",
      "value2": "v2"
    },
    "ddd": {
      "value3": "v3",
      "value4": 4
    }
  },
  "status": 200
}

他のキー(期待される結果など)も取り除く場合は、次のようにします。

jq -s '.[0] * .[1] | {value: .value}' file1 file2

または、おそらくやや効率的です(他の値をマージしないため)。

jq -s '.[0].value * .[1].value | {value: .}' file1 file2

2
-sフラグがないと、2つのオブジェクトが配列にないため、フラグは重要です。
John Morales、

1
@SimoKinnunenここでは、2つのjsonファイルをマージしています。1つのjson変数と他のjsonファイルを持つことは可能ですか?試しましたがうまくいかないようです!
Jayesh Dhandha

個々のファイルがキーでソートされている場合、結果のファイルで順序を維持することは可能ですか?
レオ

@SimoKinnunen次のコマンドを使用しています: "jq -s 'add' config.json other / *。json"しかし、 "cat config.json"を実行すると、マージされません。出力をファイルに戻すにはどうすればよいですか?
Renato Bibiano

63

使用jq -s add

$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
  "a": 0,
  "b": "bar",
  "c": "baz"
}

これは、すべてのJSONテキストをstdinから配列に読み取り(jq -sそれを行います)、それらを「削減」します。

addとして定義されますdef add: reduce .[] as $x (null; . + $x);。これは、入力配列/オブジェクトの値を反復処理してそれらを追加します。オブジェクト追加==マージ。)


4
このアプローチで再帰的マージ(*演算子)を実行することは可能ですか?
デイブフォスター、

1
@DaveFosterはい、次のようなものがありますreduce .[] as $x ({}; . * $x)jribの回答も参照してください。
Chriki、

これは、Ansibleとjqを使用して2つのjsonファイルをマージするのに役立ちました。ありがとう。
フェリペアルバレス

35

それがまだ必要かどうかは誰にもわかりませんが、これが解決策です。

--slurpオプションが表示されたら、それは簡単です。

--slurp/-s:
    Instead of running the filter for each JSON object in the input,
    read the entire input stream into a large array and run the filter just once.

次に、+オペレーターはあなたが望むことをします:

jq -s '.[0] + .[1]' config.json config-user.json

(注:左のファイルを右のファイルで上書きするのではなく、内部オブジェクトをマージする場合は、手動で行う必要があります)


19

以下*は、任意の数のオブジェクトに対して(を使用して)再帰的に機能するバージョンです。

echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --slurp 'reduce .[] as $item ({}; . * $item)'
{
  "A": {
    "a": 1,
    "b": 2
  },
  "B": 3
}

2
すばらしい答えです。ディレクトリ内のすべてのファイルをマージするときにうまく機能します:jq -s 'reduce .[] as $item ({}; . * $item)' *.json
John Ellmore

7

まず、{"value":.value}は単に{value}に短縮できます。

第2に、-argfileオプション(jq 1.4およびjq 1.5で使用可能)は、-slurpオプションを使用する必要がないので興味深いかもしれません。

これらをまとめると、2つのファイル内の2つのオブジェクトは、次のように指定された方法で結合できます。

$ jq -n --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'

ここでは--argfileオプションからの入力であるため、「-n」フラグは、jdinにstdinから読み取らないように指示します。


2
jqは廃止され--argileました--slurpfile
David

3

これは、コマンドで指定された任意の数のファイルをマージするために使用できます。

jq -rs 'reduce .[] as $item ({}; . * $item)' file1.json file2.json file3.json ... file10.json

またはこれは任意の数のファイルに対して

jq -rs 'reduce .[] as $item ({}; . * $item)' ./*.json

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.