The tricky part is to "flatten" the dictionary so you look at all the keys.
a = [
{
"type": "X",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": 1
}
},
{
"type": "X",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": 0
}
},
{
"type": "X",
"payload": {
"column1": "",
"column2": [1, 2, 3],
"column3": 1
}
},
{
"type": "X",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": None
}
},
{
"type": "X",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": {}
}
}
]
def empty_key(dictionary):
"""Recursively scan dictionary for values that are empty collections or None.
Return associated key and value or None if no 'empty' values found."""
for key in dictionary.keys():
value = dictionary[key]
if value is None:
return key, value
elif isinstance(value, (list, tuple, set, str)) and not value:
return key, value
elif isinstance(value, dict):
if value:
if (value := empty_key(value)):
return value
else:
return key, value # Empty dictionary
return None
print([x for x in a if empty_key(x) is None])
This is easily expanded to not only scan dictionary values but list, tuple, and set values as well.
a = [
{
"type": "Not empty",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": 1
}
},
{
"type": "Zero, Not empty",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": 0
}
},
{
"type": "column1 is empty str",
"payload": {
"column1": "",
"column2": [1, 2, 3],
"column3": 1
}
},
{
"type": "column3 is None",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": None
}
},
{
"type": "column3 is empty dictionary",
"payload": {
"column1": "Y",
"column2": [1, 2, 3],
"column3": {}
}
},
{
"type": "Column2 has empty list in list",
"payload": {
"column1": "Y",
"column2": [1, 2, []],
"column3": {"A":1}
}
}
]
def isempty(thing):
"""Recursively scan for emptyness. Return True if emptyness is found
in the form of an empty string, list, tuple, set or dictionary."""
if isinstance(thing, str):
if not thing:
return True
elif isinstance(thing, (list, tuple, set)):
if not thing:
return True
for subthing in thing:
if isempty(subthing):
return True
elif isinstance(thing, dict):
if not thing:
return True
for subthing in thing.values():
if isempty(subthing):
return True
return False
for thing in [x for x in a if isempty(x)]:
print(thing)
Output:
{'type': 'column1 is empty str', 'payload': {'column1': '', 'column2': [1, 2, 3], 'column3': 1}}
{'type': 'column3 is None', 'payload': {'column1': 'Y', 'column2': [1, 2, 3], 'column3': None}}
{'type': 'column3 is empty dictionary', 'payload': {'column1': 'Y', 'column2': [1, 2, 3], 'column3': {}}}
{'type': 'Column2 has empty list in list', 'payload': {'column1': 'Y', 'column2': [1, 2, []], 'column3': {'A': 1}}}