用 JQ 修改嵌套的 JSON 数组

modify nested JSON array with JQ

我想用JQ修改以下JSON输入:

{
  "rows": [
    {
      "fields": [
        {
          "name": "id",
          "value": "k1"
        },
        {
          "name": "val",
          "value": "2340378b211aa3d8f2d7607cbddce883b87b191d0425736641e3d308ea329718"
        },
        {
          "name": "Encoding",
          "value": "hex"
        }
      ]
    },
    {
      "fields": [
        {
          "name": "id",
          "value": "k2"
        },
        {
          "name": "val",
          "value": "2340378b211aa3d8f2d7607cbddce883b87b191d0425736641e3d308ea329718"
        },
        {
          "name": "Encoding",
          "value": "hex"
        }
      ]
    }
  ]
}

以便将名称为 "Encoding""value" 字段的 "hex" 值修改为 "oct" only包含 .name=="id" and .value=="k1".

字段的行

我该怎么做?我可以 select 一个带有 .value=="k1" 等的字段,但我似乎无法找到一种方法 "go up the tree" 随后更新 "Encoding" 字段。

不能期望输入具有固定的 field/row 顺序。

使用 any/2 生成一个 jq 过滤器,与问题的英文描述非常匹配:

.rows |= map( if any(.fields[]; .name=="id" and .value=="k1")
              then .fields |= map(if .name == "Encoding"
                                  then .value = "oct"
                                  else .
                                  end)
              else .
              end )

使用when/2

如果我们使用如下定义的方便的通用函数,则可能会出现稍微不那么冗长且可能更清晰的解决方案:

def when(filter; action): if (filter?) // null then action else . end;

然后我们可以简单地写成:

.rows[] |= when( any(.fields[]; .name=="id" and .value=="k1");
                 .fields |= map( when (.name == "Encoding";
                                       .value = "oct")))

注意事项

  • 在将其更改为 "oct".
  • 之前,您可能需要检查 .value == "hex" 是否
  • 上述过滤器可能会在每个 "row".
  • 中改变一对以上 name/value 对