How to merge 2 json file using jq?

I am using jq tools (jq-json-processor) in a shell script to parse json.

I have 2 json files and want to merge them into one unique file

Here are the contents of the files:

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

Expected Result

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

I try to combine a lot, but the only result I get is the following: this is not the expected result:

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

With this command:

 jq -s '.[].value' file1 file2 
+47
json command-line shell jq
Oct 22 '13 at
source share
5 answers

Starting from 1.4, this is now possible with the * operator. When defining two objects, it will regress them. For example,

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

You'll get:

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

If you also want to get rid of other keys (for example, the expected result), one way to do this is:

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

Or, presumably, somewhat more efficient (since it does not combine any other values):

 jq -s '.[0].value * .[1].value | {value: .}' file1 file2 
+44
Jul 23 '14 at 7:27
source share

Use jq -s add :

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

This reads all JSON texts from stdin into an array ( jq -s does this), then it โ€œreducesโ€ them.

( add defined as def add: reduce .[] as $x (null; . + $x); which iterates over the values โ€‹โ€‹of the input array / object and adds them. Adding an object == merge.)

+29
Jun 19 '14 at 6:29
source share

Who knows if you still need it, but here is the solution.

Once you get to the --slurp option, it's easy!

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

Then the + operator will do what you want:

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

(Note: if you want to combine internal objects, and not just rewrite the left file with the necessary files, you will need to do this manually)

+20
Mar 01 '14 at 10:21
source share

Here is a version that works recursively (using * ) on an arbitrary number of objects:

 echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --slurp 'reduce .[] as $item ({}; . * $item)' { "A": { "a": 1, "b": 2 }, "B": 3 } 
+8
Mar 25 '16 at 10:17
source share

First, {"value":. Value} can be shortened to simply the value {.}.

Secondly, the -argfile option (available in jq 1.4 and jq 1.5) may be of interest because it avoids the use of the -slurp option.

Combining them, two objects in two files can be combined as follows:

 $ jq --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}' 
+1
Aug 10 '15 at 4:43
source share



All Articles