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