'Remove empty elements from nested JSON

I have a nested json with an arbitrary depth level :

json_list = [
    { 
        'class': 'Year 1', 
        'room': 'Yellow',
        'students': [
            {'name': 'James', 'sex': 'M', 'grades': {}},
        ]
    },
    { 
        'class': 'Year 2',
        'info': {
            'teachers': { 
                'math': 'Alan Turing', 
                'physics': []
            }
        },
        'students': [
            { 'name': 'Tony', 'sex': 'M', 'age': ''},
            { 'name': 'Jacqueline', 'sex': 'F' },
        ],
        'other': []
    }
]

I want to remove any element that its value meet certain criteria.

For example:

values_to_drop = ({}, (), [], '', ' ')
filtered_json = clean_json(json_list, values_to_drop)
filtered_json

Expected Output of clean_json:

[
    { 
        'class': 'Year 1', 
        'room': 'Yellow',
        'students': [
            {'name': 'James', 'sex': 'M'},
        ]
    },
    { 
        'class': 'Year 2',
        'info': {
            'teachers': { 
                'math': 'Alan Turing', 
            }
        },
        'students': [
            { 'name': 'Tony', 'sex': 'M'},
            { 'name': 'Jacqueline', 'sex': 'F'},
        ]
    }
]

I thought of something like first converting the object to string using json.dumps and then looking in the string and replacing each value that meets the criteria with some kind of flag to filter it after before reading it again with json.loads but I couldn't figure it out and I don't know if this is the way to go



Solution 1:[1]

I managed to get the desired output by tweaking this answer a bit:

def clean_json(json_obj, values_to_drop):
    if isinstance(json_obj, dict):
        json_obj = {
            key: clean_json(value, values_to_drop) 
            for key, value in json_obj.items()
            if value not in values_to_drop}
    elif isinstance(json_obj, list):
        json_obj = [clean_json(item, values_to_drop)
                  for item in json_obj
                  if item not in values_to_drop]
    return json_obj

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 abdelgha4