【问题标题】:Using JQ to inject element at specific position based on conditions使用JQ根据条件在特定位置注入元素
【发布时间】:2021-05-07 10:21:52
【问题描述】:

扯我的头发,尝试使用jq解析和扩展一个JSON文件,并根据一定的条件在特定位置添加一个元素。 这是一个示例文件(也位于https://jqplay.org/s/6cjmbnvrqu

{
  "TopA": { "stuff": "here"},
  "TopB": {
    "C591AB7E": {
      "Type": "this",
      "Properties": {
        "lots": 1,
        "of": 2,
        "values" : 3
      }
    },
    "7E16765A": {
      "Type": "this",
      "Properties": {
        "lots": 4,
        "of": 5,
        "values" : 6
      }
    },
    "AAD76465": {
      "Type": "that",
      "Properties": {
        "lots": 7,
        "of": 8,
        "values" : 9
      }
    }
  }
}

目标是将元素添加到 .Type == "that" 的任何 TopB 子节点的 Properties 节点。更重要的是,我需要将子节点的键放入带有添加前缀的新元素值中。 所以基本上我需要最后一个元素看起来像这样:

"AAD76465": {
  "Type": "that",
  "Properties": {
    "lots": 7,
    "of": 8,
    "values": 9,
    "newElement": "Prefix-AAD76465"
  }
}

我还需要保留整个文件的其余部分(或一个新文件)。所以我不需要查询,而是需要一个 jq 调用来操作现有文件。与 TopB 平行,文件中可能还需要其他元素。不,我不知道,我也无法控制 TopB 的孩子的命名。我所拥有的只是我的目标是带有.Type ==“that”的TopB 的嵌套子级。可以有多个。

感谢收看。

【问题讨论】:

    标签: json select key jq


    【解决方案1】:

    如果您获得了将首先添加新字段的路径,则可以简单地从中提取父键。

    reduce path(.TopB[] | select(.Type == "that") .Properties.newElement) as $p (.; setpath($p; "Prefix-\($p[1])"))
    

    Online demo

    【讨论】:

      【解决方案2】:

      这是一个使用 walk/1 的解决方案,因此可能非常直观:

      walk(if (type == "object") and .TopB
           then .TopB |= with_entries( 
             .key as $key
             | if .value.Type == "that" 
               then .value.Properties += { newElement: ("Prefix-" + $key) }
               else . end)
           else . end)
      

      此解决方案的一个优点是它满足规定的要求:

      目标是向任何 TopB 子节点的 Properties 节点添加一个元素...

      从某种意义上说,没有对带有“topB”键的对象的位置做出任何假设。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-27
        相关资源
        最近更新 更多