问题
I would like to use JQ to modify the following JSON input:
{
"rows": [
{
"fields": [
{
"name": "id",
"value": "k1"
},
{
"name": "val",
"value": "2340378b211aa3d8f2d7607cbddce883b87b191d0425736641e3d308ea329718"
},
{
"name": "Encoding",
"value": "hex"
}
]
},
{
"fields": [
{
"name": "id",
"value": "k2"
},
{
"name": "val",
"value": "2340378b211aa3d8f2d7607cbddce883b87b191d0425736641e3d308ea329718"
},
{
"name": "Encoding",
"value": "hex"
}
]
}
]
}
so that the "hex"
value of the "value"
field with name "Encoding"
is modified to "oct"
only for the row that contains a field with .name=="id" and .value=="k1"
.
How would I do that? I can select
a field with .value=="k1"
etc. but I don't seem to be able to find a way to "go up the tree" to update the "Encoding"
field subsequently.
The input cannot be expected to have a fixed field/row order.
回答1:
Using any/2
yields a jq filter that closely matches the description of the problem in English:
.rows |= map( if any(.fields[]; .name=="id" and .value=="k1")
then .fields |= map(if .name == "Encoding"
then .value = "oct"
else .
end)
else .
end )
Using when/2
A slightly less verbose and perhaps clearer solution is possible if we use a handy general-purpose function defined as follows:
def when(filter; action): if (filter?) // null then action else . end;
We can then write simply:
.rows[] |= when( any(.fields[]; .name=="id" and .value=="k1");
.fields |= map( when (.name == "Encoding";
.value = "oct")))
Caveats
- You might want to check whether .value == "hex" before changing it to "oct".
- The above filters could potentially change more than one name/value pair per "row".
来源:https://stackoverflow.com/questions/50744629/modify-nested-json-array-with-jq