简体   繁体   中英

How to use jq to selectively update JSON array, referring to parent properties

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.

As an example, take this array:

[
  {
    "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"
      }
    ]
  }
]

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 .

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.

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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM