示例JSON文件:
{
"u": "stuff",
"x": [1,2,3],
"y": {
"field": "value"
},
"z": {
"zz": {
"name": "change me",
"more": "stuff"
},
"randomKey": {
"name": "change me",
"random": "more stuff"
}
}
}
如何将所有名称字段更新为"",保持JSON文件的其余部分相同?
{
"u": "stuff",
"x": [1,2,3],
"y": {
"field": "value"
},
"z": {
"zz": {
"name": "something",
"more": "stuff"
},
"randomKey": {
"name": "something",
"random": "more stuff"
}
}
}
使用直接路径,这很容易,但父键(在这种情况下为z和randomKey)会有所不同。
我尝试过类似的事情:
jq '.z | .. | .name? |= "something"' file.json
它更新了名称,但也放了所有递归的东西..
答案 0 :(得分:1)
如果可以在任何地方更改“名称”字段,则可以使用walk/1
:
walk(if type == "object" and has("name") then .name = "something" else . end)
请注意,在jq 1.5发布后,walk/1
仅包含在jq中。如果您的jq没有它,那么您可以在jq FAQ上找到它的定义。
如果您只想修改“z”上下文中的“name”字段,请考虑:
.z |= with_entries(if .value.name?
then .value.name = "something"
else . end)
答案 1 :(得分:1)
假设z
中的每个值都有name属性,您可以这样做:
$ jq --arg newname 'something' '.z[].name = $newname' input.json
在对象上使用[]
将产生该对象中包含的所有值。对于每个值,我们只是将name
设置为新名称。
如果您需要对更新内容更具选择性,则必须为要更新的对象添加更多条件。一般来说,我使用峰值方法,但这是使用类似于第一种方法的结构可以实现的另一种方式,假设我们只想更新已经有{{{}的对象。 1}} property:
name
将作业的LHS包含在括号中非常重要,我们不希望在作业之前更改上下文,否则我们不会看到其余结果。< / p>