FJunqueira FJunqueira - 5 months ago 16
JSON Question

Using jq, how to subtract 2 arrays with different keys and values from two JSON files?

This sounds like a basic question but I have been searching for a better solution for some time already...

I have the following files:

file0.json:


{
"d": {
"aaData": [
{"a":1},
{"a":2},
{"a":3},
{"a":4}
]
}
}


and

file1.json:


[
{"b":1},
{"b":2},
{"b":7}
]


and I want a subtraction between then with the expected result:

{
"key": 3
}
{
"key": 4
}


I thought of the following command would do the job:

bash$ jq -s '[.d.aaData[].a] - [.[].b] | { key: .}' file0.json file1.json


but it gives me the following error:

Cannot index array with string "b"


What makes sense, since
[.[1].b]
would't create an array, but something like
[1][2][7]


the only way I managed to get the expected result was coding in my bash script the dirty solution:

bash$ a=$(jq '[.d.aaData[].a] | {key1: .}' file0.json)
bash$ b=$(jq '[.[].b] | {key2: . }' file1.json)
bash$ c=$(echo -n $a,$b)
bash$ echo $c
{ "key1": [ 1, 2, 3, 4 ] },{ "key2": [ 1, 2, 7 ] }
bash$ d=${c//"},{"/","}
bash$ echo $d
{ "key1": [ 1, 2, 3, 4 ] , "key2": [ 1, 2, 7 ] }
bash$ echo -n $d | jq '.key1 - .key2 | { key: .[] }'
{
"key": 3
}
{
"key": 4
}


I'm quite sure there is a better way to do it with jq.... just can't find how...

Answer

Select only the values in a that are different from all values in b.

jq -n --argfile a file0.json --argfile b file1.json '$a.d.aaData[].a as $a | select([$b[].b] | all(. != $a)) | {key: $a}'