jq:基于对象值条件递归删除对象的最简单方法 [英] jq: easiest way to recursively remove objects based on object value condition

查看:91
本文介绍了jq:基于对象值条件递归删除对象的最简单方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用jq删除

a)包含一个名为"delete_me"的密钥,并且 b)键"delete_me"满足某些预定条件(空,非零,真等)

a) contain a key named "delete_me", AND b) where the key "delete_me" meets some predetermined condition (null, non-zero, true, etc)

基本上,我要实现的逻辑是:遍历输入,然后在每个节点上,如果该节点不是数组或对象,则继续进行操作,否则,继续进行处理,但从中删除任何子级是条件a)或b)失败的字典.

Basically, the logic I want to implement is: walk the input, and at each node, if that node is not an Array or an Object, then keep it and move on, otherwise, keep it but remove from it any children that are dictionaries for which either condition a) or b) fail.

有什么建议吗?

样本输入:

{
  "a": { "foo": "bar" },
  "b": {
    "i": {
      "A": {
        "i": [
          {
            "foo": {},
            "bar": {
              "delete_if_this_is_null": false,
              "an_array": [],
              "another_array": [
                {
                    "delete_if_this_is_null": null,
                    "foo": "bar"
                }
              ],
              "etc": ""
            },
            "foo2": "s"
          },
          {
            "foo": {
              "an_array": [
                {
                  "delete_if_this_is_null": "ok",
                  "foo":"bar",
                  "another_object": { "a":1 }
                },
                {
                  "delete_if_this_is_null": null,
                  "foo2":"bar2",
                  "another_object": { "a":1 },
                  "name": null
                }
              ],
              "an_object": {
                "delete_if_this_is_null":null,
                "foo3":"bar3"
              }
            },
            "zero": 0,
            "b": "b"
          }
        ]
      }
    }
  }
}

如果delete_if_this_is_null并且预定条件为delete_if_this_is_null == null,则

应该产生:

should yield, if the "delete_me" key is delete_if_this_is_null and the predetermined condition is delete_if_this_is_null == null:

{
  "a": { "foo": "bar" },
  "b": {
    "i": {
      "A": {
        "i": [
          {
            "foo": {},
            "bar": {
              "delete_if_this_is_null": false,
              "an_array": [],
              "another_array": [],
              "etc": ""
            },
            "foo2": "s"
          },
          {
            "foo": {
              "an_array": [
                {
                  "delete_if_this_is_null": "ok",
                  "foo":"bar",
                  "another_object": { "a":1 }
                }
              ]
            },
            "zero": 0,
            "b": "b"
          }
        ]
      }
    }
  }
}


更新:这是解决方案:假设输入位于文件"input.json"中:


UPDATE: Here's the solution: Assume the input is in a file 'input.json':

jq 'def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;

def mapper(f):
  if type == "array" then map(f)
  elif type == "object" then
  . as $in
  | reduce keys[] as $key
      ({};
       [$in[$key] | f ] as $value
       | if $value | length == 0 then .
         else . + {($key): $value[0]} end)
  else .
  end;

walk( mapper(select((type == "object" and .delete_if_this_is_null == null) | not)) )' < input.json

推荐答案

Jeff的解决方案可能会改变得太多.例如,使用:

Jeff's solution may zap too much. For example, using:

def data: [1,2, {"hello": {"delete_me": true, "a":3 }, "there": 4} ]; ];

Jeff的解决方案产生了空值(即无结果).

Jeff's solution yields empty (i.e. nothing).

因此,以下内容可能更接近您要寻找的内容:

The following may therefore be closer to what you're looking for:

walk(if (type == "object" and .delete_me) then del(.) else . end )

对于data,结果为:

[1,2,{"hello":null,"there":4}]

替代解决方案

如果在上面的示例中需要消除"hello":null的解决方案,则需要jq的map_values/1的变体.这是一种方法:

Alternative Solution

If a solution that eliminates the "hello":null in the above example is required, then a variant of jq's map_values/1 is needed. Here's one approach:

def mapper(f):
  if type == "array" then map(f)
  elif type == "object" then
  . as $in
  | reduce keys[] as $key
      ({};
       [$in[$key] | f ] as $value
       | if $value | length == 0 then . 
         else . + {($key): $value[0]} end)
  else .
  end;

data | walk( mapper(select((type == "object" and .delete_me) | not)) )

结果是:

[1,2,{"there":4}]

这篇关于jq:基于对象值条件递归删除对象的最简单方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆