'Removing and adding key-value from JSON file using jq
I have an json file as follows below-
{
"key1": [
"value1"
],
"key2": [
"value2"
],
"key3": [
"value3"
],
"key4": {
"name": "value4"
},
"key5": [
{
"field1": "abc",
"field2": "xyz"
}
]
}
I want to remove field 2 from key5 array and add another field say field3 in key5 array using jq I tried various way but couldn't figure it how to do this in single command. Can you please help . Thanks in advance
Solution 1:[1]
This assumes that the insert and deletion keys (field2
and field3
) are also dynamic, not just the inserted value.
- Use
--arg
and--argjson
to initialize variables with values from outside the filter, herefield2
as a string and{"field3": "new"}
as a JSON object - Use the update operator
|=
on the element you want to change, here.key5[]
.- Note:
.key5
is an array, not an object, thus it has no fields. But the array does contain objects as its elements. Using.key5[]
to access the array elements will update all objects in the array. To update just one of them, say, the first one, use.key[0]
instead.
- Note:
- Use
delpaths
to delete a given path, here the top-level field[$delkey]
. - Use simple addition
+
to add a new key/value pair as object, here$add
.
jq --arg delkey 'field2' --argjson addobj '{"field3": "new"}' '
.key5[] |= delpaths([[$delkey]]) + $addobj
' input.json
{
"key1": [
"value1"
],
"key2": [
"value2"
],
"key3": [
"value3"
],
"key4": {
"name": "value4"
},
"key5": [
{
"field1": "abc",
"field3": "new"
}
]
}
If you want to provide the new object's key and value separately, i.e. as strings, not as a pre-composed JSON, you need a third input variable
jq --arg delkey 'field2' --arg addkey 'field3' --arg addval 'new' '
.key5[] |= (delpaths([[$delkey]]) | .[$addkey] = $addval)
' input.json
Solution 2:[2]
.key5[] |= ( ... )
allows you to modify each element of the array found at .key5
.
Therein, we can use the usual commands for deleting and adding fields.
jq '.key5[] |= ( del( .field2 ) | .field3 = "foo" )'
Demo in jqplay
Here's a variation where the value to add is provided as a command-line argument:
jq --arg val foo '.key5[] |= ( del( .field2 ) | .field3 = $val )'
Solution 3:[3]
Try filter:
del(.key5[0].field2) | .key5[0] |= .+{field3:"foo"}
Output:
{
"key1": [
"value1"
],
"key2": [
"value2"
],
"key3": [
"value3"
],
"key4": {
"name": "value4"
},
"key5": [
{
"field1": "abc",
"field3": "foo"
}
]
}
Demo
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Logan Lee |