I have the following JSON input:
{
"a": {
"a": "foo",
"b": "bar"
},
"b": {
"a": [],
"b": []
},
"c": {},
"d": [
"foo",
"bar"
]
}
I want to recursively remove all the keys that point at empty arrays or objects, so that the result looks like:
{
"a": {
"a": "foo",
"b": "bar"
},
"d": [
"foo",
"bar"
]
}
What I’ve come up with is:
jq 'walk(if ((type=="object" or type=="array") and length==0) then empty else . end)'
But this deletes everything but the last array:
{
"d": [
"foo",
"bar"
]
}
If I change empty
to {"A":1}
:
jq 'walk(if ((type=="object" or type=="array") and length==0) then {"A":1} else . end)'
I get what I expect, where the first, populated object remains untouched:
{
"a": {
"a": "foo",
"b": "bar"
},
"b": {
"a": {
"A": 1
},
"b": {
"A": 1
}
},
"c": {
"A": 1
},
"d": [
"foo",
"bar"
]
}
So why is it when I instead tell it to replace zero-length arrays and objects with empty
that it attacks non-zero-length objects? What am I doing wrong?
2
Answers
Here is one way to do it:
Online demo
Here’s a solution using
walk
andIN
: