'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
--argand--argjsonto initialize variables with values from outside the filter, herefield2as a string and{"field3": "new"}as a JSON object - Use the update operator
|=on the element you want to change, here.key5[].- Note:
.key5is 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
delpathsto 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 |
