2013-10-22 14 views
53

私はシェルスクリプトでjqツール(jq-json-processor)を使用してjsonを解析しています。2 jsonファイルをjqを使ってマージするには?

file1の

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

FILE2

は、私は2つのJSONファイルと を持って

は、ここに1つのユニークなファイル

ファイルの内容にそれらをマージしたいです

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

私はcombinaisonの多くを試みるが、私が得る唯一の結果が期待された結果ではない、以下、次のとおりです。このコマンドを使用して

{ 
    "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を試しましたか? https://github.com/trentm/json –

+0

まだ、私は見ています。 Thx – Janfy

+0

'json'でこれを行うには:' cat f1 f2 | json --deep-merge' – xer0x

答えて

50

addは、入力配列の/オブジェクトの値に対するその反復し、それらを加算する。加算オブジェクト==マージ。、def add: reduce .[] as $x (null; . + $x);として定義されます)。 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 
} 

あなたも(あなたの期待された結果のような)他のキーを取り除きたい場合は、それを行うための一つの方法はこれです:

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

それとも、おそらく多少、より効率的な(それは他の値をマージしていないため):

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

_NOTE_: '-s'フラグは、2つのオブジェクトが配列にないので、重要です。 –

20

あなたがまだそれを必要としているかどうかは知っていますが、解決策はここにあります。

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

(注:ちょうど右のファイルのもので、左のファイルのものを上書きするのではなく、内側のオブジェクトをマージしたい場合、あなたは意志使用 jq -s add

30

に)それを手動で実行する必要があります。

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

これは、すべてのJSONテキストをstdinから配列に読み込み(jq -sする)、それを "減らし"ます。

この*演算子で可能になりました1.4ので

+4

この方法で再帰的マージ(*演算子)を行うことは可能ですか? –

+0

@DaveFosterはい、$ x({};。* $ x)と 'reduce。[]などのようなものです。 - [jribの回答](http://stackoverflow.com/a/36218044/1797912)も参照してください。 – Chriki

2

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

第2に、--slurpオプションを使用する必要がないため、--argfileオプション(jq 1.4とjq 1.5で使用可能)が重要です。次のように一緒にこれらを置く

は、2つのファイルに2つのオブジェクトが指定された方法で組み合わせることができます

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

ここでオブジェクトの任意の数に(*を使用して)再帰的に動作するバージョンがあります:

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