[英]jq: easiest way to recursively remove objects based on object value condition
我想使用jq
刪除JSON“對象”(我通常使用該術語指代數組或字典)中的所有字典
a)包含一個名為“ delete_me”的鍵,並且b)其中鍵“ delete_me”滿足某些預定條件(null,非零,true等)
基本上,我要實現的邏輯是:遍歷輸入,然后在每個節點上,如果該節點不是數組或對象,則繼續輸入並繼續前進,否則,保留它,但從中刪除任何字典的子級條件a)或b)失敗。
有什么建議么?
輸入樣例:
{
"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_me”鍵為delete_if_this_is_null
並且預定條件為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"
}
]
}
}
}
}
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
這是使用遞歸函數的解決方案:
def clean(condition):
if type == "object" then
if condition
then empty
else
with_entries(
if (.value|type) == "object" and (.value|condition)
then empty
else .value |= clean(condition)
end
)
end
elif type == "array" then
map(
if type == "object" and condition
then empty
else clean(condition)
end
)
else .
end
;
clean(
has("delete_if_this_is_null") and (.delete_if_this_is_null == null)
)
我不確定您要在問題中完成什么,但是我假設您要遞歸搜索json響應並刪除滿足某些條件的json對象。
您可以使用的幫助做到這一點比較容易walk
過濾器將在JQ的未來版本中來了,看到在實施源 。
# Apply f to composite entities recursively, and to atoms
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 filter_objects(predicate): # removes objects that satisfies some predicate
walk(
if (type == "object") and (predicate) then
empty
else
.
end
)
;
filter_objects(.delete_me) # remove objects that has a truthy property "delete_me"
傑夫的解決方案可能會改變得太多。 例如,使用:
def data: [1,2, {"hello": {"delete_me": true, "a":3 }, "there": 4} ]; ];
傑夫的解決方案得出的結果是空的(即什么也沒有)。
因此,以下內容可能更接近您要尋找的內容:
walk(if (type == "object" and .delete_me) then del(.) else . end )
對於data
,得出:
[1,2,{"hello":null,"there":4}]
如果需要在上面的示例中消除"hello":null
的解決方案,則需要jq的map_values / 1的變體。 這是一種方法:
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}]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.