jq:基于对象值条件递归删除对象的最简单方法 [英] jq: easiest way to recursively remove objects based on object value condition
问题描述
我想使用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"
}
]
}
}
}
}
如果 应该产生: should yield, if the "delete_me" key is delete_if_this_is_null == null
,则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屋!