I want to update a value in a dict, which I can only identify by another value in the dict. That is, given this input:
[
{
"format": "geojson",
"id": "foo"
},
{
"format": "geojson",
"id": "bar"
},
{
"format": "zip",
"id": "baz"
}
]
I want to change baz
's accompanying format to 'csv':
[
{
"format": "geojson",
"id": "foo"
},
{
"format": "geojson",
"id": "bar"
},
{
"format": "csv",
"id": "baz"
}
]
I have found that this works:
jq 'map(if .id=="baz" then .format="csv" else . end)' my.json
But this seems rather verbose, so I wonder if there is a more elegant way to express this. jq seems to be missing some kind of expression selector, the equivalent of might be [@id='baz']
in xpath.
(When I started this question, I had [.[] |...]
, then I discovered map
, so it's not quite as bad as I thought.)
In this article, we will update the values of a list of dictionaries. The append function is used to insert a new value in the list of dictionaries, we will use pop () function along with this to eliminate the duplicate data. This function is used to insert updated data based on an index.
If you want to update the value of ‘b’ to 7, you can write as d ['b']=7. However the same method cannot be applied to nested ones. That will create a new key as the keys in outer dictionary will only be searched while you try to update. For example, see the code below:
In the example above, we created new JSON from scratch. jq is equally useful for updating existing JSON data. In this example, we’ll start with a JSON object that defines a command to be executed and any environment variables that should be set when the command is run:
When running jq, the following arguments may become handy: Output the jq version and exit with zero. Output the fields of each object with the keys in sorted order.
A complex assignment is what you're looking for:
jq '(.[] | select(.id == "baz") | .format) |= "csv"' my.json
Perhaps not shorter but it is more elegant, as requested. See the last section of the docs at: http://stedolan.github.io/jq/manual/#Assignment
Edit: using map
:
jq 'map((select(.id == "baz") | .format) |= "csv")' my.json
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With