使用 jq 修改 JSON 中的值:在值前面加上父键的名称
Modify value in JSON with jq: prepend value with name of parent key
我的想法是我有一个对象,它是数组的一部分,它本身就是父键的值。我想使用该键的值来更改原始子对象中的值。
这是我想出的办法,虽然它有效,但我不禁认为还有更好的方法。这太不直观了,我至少花了 3 个小时的试验结束错误来确定语法并删除错误。
echo '{"red": [{"fruit": "apple", "grows_on":"tree"}, {"fruit":"raspberry","grows_on":"vine"}], "green": [{"fruit": "apple", "grows_on":"tree"}, {"fruit":"gooseberry","grows_on":"bush"}]}' |
jq '
walk(
if type=="object" then
with_entries(
if .key == "red" then
with_entries(
walk(
if type=="object" then
with_entries(
if .key=="fruit" then
.value= "red" + "_" + .value
else . end
)
else . end
)
)
elif .key == "green" then
with_entries(
walk(
if type=="object" then
with_entries(
if .key=="fruit" then
.value= "green" + "_" + .value
else . end
)
else . end
)
)
else . end
)
else . end
)'
{
"red": [
{
"fruit": "red_apple",
"grows_on": "tree"
},
{
"fruit": "red_raspberry",
"grows_on": "vine"
}
],
"green": [
{
"fruit": "green_apple",
"grows_on": "tree"
},
{
"fruit": "green_gooseberry",
"grows_on": "bush"
}
]
}
您可以使用 with_entries
(它本身是 to_entries | map(…) | from_entries
的快捷方式)将每个字段解构为 key-value 对,通过访问键和值来根据自己的喜好进行操作,并再次重建它。
内部过滤器将键保存到一个变量中,下降到每个值的 fruit
并根据键及其当前名称 .
.
更新其名称 |=
jq 'with_entries(.key as $key | .value[].fruit |= $key + "_" + .)'
{
"red": [
{
"fruit": "red_apple",
"grows_on": "tree"
},
{
"fruit": "red_raspberry",
"grows_on": "vine"
}
],
"green": [
{
"fruit": "green_apple",
"grows_on": "tree"
},
{
"fruit": "green_gooseberry",
"grows_on": "bush"
}
]
}
如果您只想更新名为 red
或 green
的 top-level 对象的字段,以及名为 fruit
的值数组的对象项的字段(这是您的检查正在进行),您可以结合使用 objects
(这是 select(type == "object")
的快捷方式)和适当的检查。
jq '
objects |= with_entries(.key as $key | if IN("red", "green"; $key) then
(.value[] | objects.fruit // empty) |= $key + "_" + .
else . end)
'
我的想法是我有一个对象,它是数组的一部分,它本身就是父键的值。我想使用该键的值来更改原始子对象中的值。
这是我想出的办法,虽然它有效,但我不禁认为还有更好的方法。这太不直观了,我至少花了 3 个小时的试验结束错误来确定语法并删除错误。
echo '{"red": [{"fruit": "apple", "grows_on":"tree"}, {"fruit":"raspberry","grows_on":"vine"}], "green": [{"fruit": "apple", "grows_on":"tree"}, {"fruit":"gooseberry","grows_on":"bush"}]}' |
jq '
walk(
if type=="object" then
with_entries(
if .key == "red" then
with_entries(
walk(
if type=="object" then
with_entries(
if .key=="fruit" then
.value= "red" + "_" + .value
else . end
)
else . end
)
)
elif .key == "green" then
with_entries(
walk(
if type=="object" then
with_entries(
if .key=="fruit" then
.value= "green" + "_" + .value
else . end
)
else . end
)
)
else . end
)
else . end
)'
{
"red": [
{
"fruit": "red_apple",
"grows_on": "tree"
},
{
"fruit": "red_raspberry",
"grows_on": "vine"
}
],
"green": [
{
"fruit": "green_apple",
"grows_on": "tree"
},
{
"fruit": "green_gooseberry",
"grows_on": "bush"
}
]
}
您可以使用 with_entries
(它本身是 to_entries | map(…) | from_entries
的快捷方式)将每个字段解构为 key-value 对,通过访问键和值来根据自己的喜好进行操作,并再次重建它。
内部过滤器将键保存到一个变量中,下降到每个值的 fruit
并根据键及其当前名称 .
.
|=
jq 'with_entries(.key as $key | .value[].fruit |= $key + "_" + .)'
{
"red": [
{
"fruit": "red_apple",
"grows_on": "tree"
},
{
"fruit": "red_raspberry",
"grows_on": "vine"
}
],
"green": [
{
"fruit": "green_apple",
"grows_on": "tree"
},
{
"fruit": "green_gooseberry",
"grows_on": "bush"
}
]
}
如果您只想更新名为 red
或 green
的 top-level 对象的字段,以及名为 fruit
的值数组的对象项的字段(这是您的检查正在进行),您可以结合使用 objects
(这是 select(type == "object")
的快捷方式)和适当的检查。
jq '
objects |= with_entries(.key as $key | if IN("red", "green"; $key) then
(.value[] | objects.fruit // empty) |= $key + "_" + .
else . end)
'