Json 替换jq中没有精确路径的子键

Json 替换jq中没有精确路径的子键,json,nested,key,updates,jq,Json,Nested,Key,Updates,Jq,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": "change me",
       "more": "stuff"
    },
    "randomKey":  {
       "name": "change me",
       "random": "more stuff"
    }
  }
}
如何将所有名称字段更新为“something”,保持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

它会更新名称,但也会放入所有递归内容。

如果可以在任何地方更改“name”字段,您可以使用
walk/1

walk(if type == "object" and has("name") then .name = "something" else . end)
请注意,
walk/1
仅在JQ1.5发布后才包含在jq中。如果您的jq没有它,那么您可以在上找到它的定义,例如

如果只想修改“z”上下文中的“name”字段,请考虑:

.z |= with_entries(if .value.name?
                   then .value.name = "something" 
                   else . end)

假设
z
中的每个值都有name属性,则可以执行以下操作:

$ jq --arg newname 'something' '.z[].name = $newname' input.json
在对象上使用
[]
将生成该对象中包含的所有值。对于这些值中的每一个,我们只是将
名称
设置为新名称


如果您需要对更新的对象更具选择性,则必须为要更新的对象添加更多条件。一般来说,我会使用peak的方法,但这里有另一种方法,可以使用类似于第一种方法的结构来实现,假设我们只想更新已经具有
名称
属性的对象:

$ jq --arg newname 'something' '(.z[] | select(has("name")).name) = $newname' input.json
将赋值的左括号括起来很重要,我们不想在赋值之前更改上下文,否则我们将看不到剩余的结果