修改 JSON jq 中的键值数组

Modifying array of key value in JSON jq

以防万一,我有一个原始的 json 如下所示:

{
  "taskDefinition": {
    "containerDefinitions": [
      {
        "name": "web",
        "image": "my-image",
        "environment": [
          {
            "name": "DB_HOST",
            "value": "localhost"
          },
          {
            "name": "DB_USERNAME",
            "value": "user"
          }
        ]
      }
    ]
  }
}

我想就地修改匹配键的值,如下所示:

jq '.taskDefinition.containerDefinitions[0].environment[] | select(.name=="DB_USERNAME") | .value="new"' json

我得到了输出

{
  "name": "DB_USERNAME",
  "value": "new"
}

但我想要更像就地修改或整个 json 从原来的新值修改,像这样:

{
      "taskDefinition": {
        "containerDefinitions": [
          {
            "name": "web",
            "image": "my-image",
            "environment": [
              {
                "name": "DB_HOST",
                "value": "localhost"
              },
              {
                "name": "DB_USERNAME",
                "value": "new"
              }
            ]
          }
        ]
      }
    }

是否可以使用 jq 或任何已知的解决方法?

谢谢。

已更新

任何想要编辑多值的人, 这是我使用的方法

JQ=""
for e in DB_HOST=rds DB_USERNAME=xxx; do
    k=${e%=*}
    v=${e##*=}
    JQ+="(.taskDefinition.containerDefinitions[0].environment[] | select(.name==\"$k\") | .value) |= \"$v\" | "
done

jq '${JQ%??}' json

我认为应该有更简洁的方法,但这似乎工作正常。

分配给路径就够了,如果你使用|=,例如

jq '
  (.taskDefinition.containerDefinitions[0].environment[] | 
   select(.name=="DB_USERNAME") | .value) |= "new"
' infile.json

输出:

{
  "taskDefinition": {
    "containerDefinitions": [
      {
        "name": "web",
        "image": "my-image",
        "environment": [
          {
            "name": "DB_HOST",
            "value": "localhost"
          },
          {
            "name": "DB_USERNAME",
            "value": "new"
          }
        ]
      }
    ]
  }
}

您可能会考虑使用此替代方法 |=:

walk( if type=="object" and .name=="DB_USERNAME" 
      then .value="new" else . end)

这是一个 select 的免费解决方案,使用 |=:

.taskDefinition.containerDefinitions[0].environment |=
  map(if .name=="DB_USERNAME" then .value = "new"
      else . end)

|= 的 LHS 表达式中避免 select 使解决方案更稳健 w.r.t。正在使用的 jq 版本。