There are plenty of examples of updating a value in a nested entry in jq, but I think I have a unique question, because the value I want to provide is already in another part of the same entry.
Given the following input:
{
"items": [
{
"name": "first"
},
{
"name": "second"
}
]
}
I want to produce this output:
{
"items": [
{
"name": "first",
"value": "first"
},
{
"name": "second",
"value": "second"
}
]
}
In other words, I want to copy the value of .name to the value of .value for each entry in items[].
Assignment is easy enough if the value is static. jq '.items[].value |= "x"
But since the value is dynamic, I always get stuck either at the wrong context level:
$ jq '.items[].value|=.name' <<< '{"items":[{"name": "first"},{"name": "second"}]}'
{
"items": [
{
"name": "first",
"value": null
},
{
"name": "second",
"value": null
}
]
}
Or with the wrong output context:
jq '.items[]|(.value=.name)' <<< '{"items":[{"name": "first"},{"name": "second"}]}'
{
"name": "first",
"value": "first"
}
{
"name": "second",
"value": "second"
}
How can I make the change within the entries, for each entry, but still output the whole thing from the top level?
>Solution :
With .items[].value |= .name, .name is a reference into the input context (the outer object in this case, thus producing null values), and with .items[] | (.value = .name), the context is right but with the pipe combinator | you give up on the previous context and can’t return to it (here, resulting in the items without the surrounding array). To keep the context, use instead the update assignment operator |= on a superordinate entity.
Either on each item of the .items array:
.items[] |= (.value = .name)
Or on the entire array using map:
.items |= map(.value = .name)
Output:
{
"items": [
{
"name": "first",
"value": "first"
},
{
"name": "second",
"value": "second"
}
]
}