Finding all elements in a JSON dictionary which are not part of another dictionary with jq - json

I have to JSON files.
a.json:
[
{ key1: "foo", key2: "bar"},
{ key1: "foo", key2: "baz"},
{ key1: "bla", key2: "blubb"},
]
b.json:
[
{ key1: "foo", key2: "bar"},
{ key1: "foo", key2: "oof"},
{ key1: "bla", key2: "bla"},
]
My desired result is an array containing all the entrise of the first dictionary which are not part of the second one (equivalent to what the DISTINCT operator would do in SQL). So the expected output would be:
[
{ key1: "foo", key2: "baz"},
{ key1: "bla", key2: "blubb"},
]
How can I achieve this using jq?

Can't find a valid duplicate, so posting this as an answer.
If you use -s (slurp), you can use object1 - object2 to get the difference between them:
jq -s '.[0] - .[1]' a b
Will output:
[
{
"key1": "foo",
"key2": "baz"
},
{
"key1": "bla",
"key2": "blubb"
}
]

Related

How to combine key values from list of dictionaries using jq [duplicate]

I have an array of objects with 2 properties, say "key" and "value":
[
{key: 1, value: a},
{key: 2, value: b},
{key: 1, value: c}
]
Now, I would like to merge the values of the "value" properties of objects with the same "key" property value. That is the previous array is transformed into:
[
{key: 1, value: [a, c]},
{key: 2, value: [b]}
]
I tried something like:
$ echo '[{"key": "1", "val": "a"}, {"key": "2", "val": "b"}, {"key": "1", "val": "c"}]' | jq '. | group_by(.["key"]) | .[] | reduce .[] as $in ({"val": []}; {"key": $in.key, "val": [$in.val] + .["val"]})'
But it triggers a jq syntax error and I have no idea why. I am stuck.
Any idea ?
Thanks
B
Your approach using reduce could be sanitized to
jq 'group_by(.["key"]) | .[] |= reduce .[] as $in (
{value: []}; .key = $in.key | .value += [$in.value]
)'
[
{
"value": [
"a",
"c"
],
"key": 1
},
{
"value": [
"b"
],
"key": 2
}
]
Demo
Another approach using map would be
jq 'group_by(.key) | map({key: .[0].key, value: map(.value)})'
[
{
"key": 1,
"value": [
"a",
"c"
]
},
{
"key": 2,
"value": [
"b"
]
}
]
Demo

Merging property values of objects with common key with jq

I have an array of objects with 2 properties, say "key" and "value":
[
{key: 1, value: a},
{key: 2, value: b},
{key: 1, value: c}
]
Now, I would like to merge the values of the "value" properties of objects with the same "key" property value. That is the previous array is transformed into:
[
{key: 1, value: [a, c]},
{key: 2, value: [b]}
]
I tried something like:
$ echo '[{"key": "1", "val": "a"}, {"key": "2", "val": "b"}, {"key": "1", "val": "c"}]' | jq '. | group_by(.["key"]) | .[] | reduce .[] as $in ({"val": []}; {"key": $in.key, "val": [$in.val] + .["val"]})'
But it triggers a jq syntax error and I have no idea why. I am stuck.
Any idea ?
Thanks
B
Your approach using reduce could be sanitized to
jq 'group_by(.["key"]) | .[] |= reduce .[] as $in (
{value: []}; .key = $in.key | .value += [$in.value]
)'
[
{
"value": [
"a",
"c"
],
"key": 1
},
{
"value": [
"b"
],
"key": 2
}
]
Demo
Another approach using map would be
jq 'group_by(.key) | map({key: .[0].key, value: map(.value)})'
[
{
"key": 1,
"value": [
"a",
"c"
]
},
{
"key": 2,
"value": [
"b"
]
}
]
Demo

Get last N elements for each item of a JSON object

Given the following JSON object, using jq, how to get the last two elements for each item?
I have been trying to find a solution with the help of jqplay.org but didn't get anywhere. While getting values out of objects having consistent key names is rather straightforward, I can't get my head around this.
Input:
{
"foo": {
"abc": { "key1": "value1" },
"bcd": { "key1": "value1" },
"cde": { "key1": "value1" },
"def": { "key1": "value1" },
"efg": { "key1": "value1" },
"fgh": { "key1": "value1" }
},
"bar": {
"ghi": { "key1": "value1" }
},
"qux": {
"hij": { "key1": "value1" },
"ijk": { "key1": "value1" },
"jkl": { "key1": "value1" },
"klm": { "key1": "value1" }
}
/* ... */
}
Expected result:
{
"foo": {
"efg": { "key1": "value1" },
"fgh": { "key1": "value1" }
},
"bar": {
"ghi": { "key1": "value1" }
},
"qux": {
"jkl": { "key1": "value1" },
"klm": { "key1": "value1" }
}
/* ... */
}
One option is to delete all fields but the last N (2 here) using delpaths. You need to convert key names to path representations though. E.g:
map_values(delpaths(keys_unsorted[:-2] | map([.])))
See the jqplay demo.
A straightforward and efficient solution:
map_values( to_entries[-2:] | from_entries)

How to select/get object elements' (array of objects) keys based on value of an element in an object in the aforementioned array in jq?

I have the following input:
{
"key1": {
"subkey1": [
{
"filterkey1": "value1",
"filterkey2": "value2"
},
{
"filterkey1": "value3",
"filterkey2": "value4"
}
],
"subkey2": [
{
"filterkey1": "value5",
"filterkey2": "value6"
},
{
"filterkey1": "value7",
"filterkey2": "value8"
}
],
"subkey3": [
{
"filterkey1": "value1",
"filterkey2": "value6"
},
{
"filterkey1": "value9",
"filterkey2": "value4"
}
]
},
"key2": {
}
}
I want to get the key of the arrays that has an object which has "value1" for key: "filterkey1". So in this case the output must be:
["subkey1", "subkey3"]
All the elements I care about are in "key1" object.
Get subkeys using keys_unsorted, and check if their values have filterkey1: "value1" pair using any:
.key1 | [
keys_unsorted[] as $k
| if any(.[$k][]; .filterkey1=="value1")
then $k
else empty end
]

Converting recursive Json String into Object in PlayFrameWork

I have a json string of format:
{ "key0" :[{
"key1": "34",
"key2": "34",
"key3": {
"key3_1": "0",
"key3_2": "0"
},
"key4": "56" },
{
"key1": "14",
"key2": "78",
"key3": {
"key3_1": "0",
"key3_2": "0"
},
"key4": "676"
}]
"key2": "value2"
}
key3 is recursice , it value is again a json string. I wrote a parse code using playframework but it gives error.
My code looks as follows:
implicit val contentReader = (
(__ \ "key0").read[List[Map[String, String]]] and
(__ \ "key4").read[String]
)(Content)
val json : JsValue = Json.parse(content)
val contentResult = json.as[Content]
Any suggestion to parse recurive json?
Thanks