web-dev-qa-db-ja.com

jqを使用して2つのjsonファイルをマージする方法は?

シェルスクリプトで jq tools(jq-json-processor)を使用して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
97
Janfy

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

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

あなたを取得します:

{
  "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
}

他のキー(予想される結果など)も削除したい場合、これを行う1つの方法は次のとおりです。

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

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

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

jq -s addを使用:

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

これにより、すべてのJSONテキストが標準入力から配列に読み込まれ(jq -sが実行します)、それらが「削減」されます。

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

47
user2259432

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

--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

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

29
FiloSottile

これは、任意の数のオブジェクトで(*を使用して)再帰的に動作するバージョンです。

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

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

次に、-argfileオプション(jq 1.4およびjq 1.5で使用可能)は、-Slurpオプションを使用する必要がないため、興味深い場合があります。

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

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

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

5
peak