如何使用jq选择性地更新JSON数组,请参考父属性

问题描述:

我正在尝试使用 jq 选择性地更改嵌套在其中的对象的单个属性一个数组,保持数组的其余部分完好无损.生成的属性值需要引用父对象的属性.

I'm trying to use jq to selectively change a single property of an object nested in an array, keeping the rest of the array intact. The generated property value needs to refer up to a property of the parent object.

以一个示例为例:

[
  {
    "name": "keep_me"
  },
  {
    "name": "leave_unchanged",
    "list": [
      {
        "id": "1",
        "key": "keep_this"
      }
    ]
  },
  {
    "name": "a",
    "list": [
      {
        "id": "2",
        "key": "also_keep_this"
      },
      {
        "id": "42",
        "key": "replace_this"
      }
    ]
  }
]

我想使用父对象的name属性来更改最后一个键(replace_this)的值,以生成类似generated_value_for_a_42的值.

I want to change the value of the last key (replace_this), using the name property of the parent object to generate a value like generated_value_for_a_42.

这里的关键问题似乎是在更新特定元素时不修改数组的其余部分.但是,需要将树"引用到父属性使事情变得复杂. 我尝试在括号中包裹更改以保持不变的元素,但是在将变量绑定(使用as)到正确的范围(访问父属性)时遇到了麻烦.因此,我要么放弃了数组或对象的一部分,要么就变量绑定遇到了错误.

The key problem here seems to be leaving the rest of the array unmodified, while updating specific elements. But the need to refer 'up the tree' to a parent property complicates matters. I tried wrapping changes in parentheses to keep untouched elements, but then had trouble with variable binding (using as) to the right scope, for accessing the parent property. So I either ended up discarding parts of the array or objects, or getting errors about the variable binding.

此答案帮助我朝着正确的方向前进.重要的学习是在正确的位置使用|=,并将过滤器包裹在if p then f else .中以保留不变的元素.

This answer helped me in the right direction. The important learnings were to use |= in the right place, and have the filters wrapped in if p then f else . to keep the unchanged elements.

以下jq脚本解决了该任务:

The following jq script solves the task:

map(.name as $name |
    if has("list")
    then .list |= map(if .key | contains("keep") | not
                      then .key = "generated_value_for_" + $name + "_" + .id
                      else .
                      end)
    else .
    end)