Search code examples
pythonjsonpython-3.xdictionaryrecursive-datastructures

Recursively Traversing Ragged JSON Hierarchy in Python 3 to perform a partial leaf node deletion


So, I have a JSON block that looks kinda like this:

[
{
    "children": [
        {
            "address": "123 Main Street",
            "class": "blarg",
            "children": [
                {
                    "children": [
                        {
                            "children": [
                                {
                                    "y_type": "string",
                                    "x_type": "002",
                                    "002_id": 2222,
                                    "updated_at": "2018-03-29T13:47:42.986Z",
                                    "field020": "AAA",
                                    "field030": "DDD"
                                },
                                {
                                    "y_type": "bool",
                                    "x_type": "007",
                                    "007_id": 2222,
                                    "updated_at": "2018-03-29T13:47:42.986Z",
                                    "field1": True,
                                    "field2": True
                                }
                            ],
                            "create_at": "2018-03-29T13:45:20.875Z",
                            "x_id": "3e0e1b44-ac0d-4bf7-985e-11d74b8be323",
                            "junk_field": {},
                            "x_type": "000",
                            "timezone": "America/New_York",
                            "update_at": "2018-03-29T13:45:20.875Z"
                        },
                        {
                            "sibling": [1,2,3]
                        }
                    ]
                }
            ]
        }
    ]
}]

What I need to do is find "children" leaf nodes that are of x_type "007" and delete the field 1 entry associated with that block of data. I'm having trouble trying to isolate the entire dict associated with only the correct kind of leaf node (children, not sibling) so that I can check it for the correct x_type and do the delete.

I'm not sure what kind of values to pass to/back from the recursive function I've sorta cobbled together. I've never done recursion in Python before, much less against ragged hierarchy JSON, so I could use some help/guidance on what approaches to use/google for. I'd appreciate any help you could give to get me goin' in the right direction!!


Solution

  • You can use dictionary unpacking with recursion:

    def d_filter(d):
      return {**({a:b for a, b in d.items() if d.get('x_type') != '007' or a != 'field1'}), \
       'children':list(map(d_filter, d.get('children', [])))} 
    
    new_data = list(map(d_filter, data))
    

    import json
    print(json.dumps(new_data, indent=4))
    

    Output:

    [
      {
        "children": [
            {
                "address": "123 Main Street",
                "class": "blarg",
                "children": [
                    {
                        "children": [
                            {
                                "children": [
                                    {
                                        "y_type": "string",
                                        "x_type": "002",
                                        "002_id": 2222,
                                        "updated_at": "2018-03-29T13:47:42.986Z",
                                        "field020": "AAA",
                                        "field030": "DDD",
                                        "children": []
                                    },
                                    {
                                        "y_type": "bool",
                                        "x_type": "007",
                                        "007_id": 2222,
                                        "updated_at": "2018-03-29T13:47:42.986Z",
                                        "field2": true,
                                        "children": []
                                    }
                                ],
                                "create_at": "2018-03-29T13:45:20.875Z",
                                "x_id": "3e0e1b44-ac0d-4bf7-985e-11d74b8be323",
                                "junk_field": {},
                                "x_type": "000",
                                "timezone": "America/New_York",
                                "update_at": "2018-03-29T13:45:20.875Z"
                            },
                            {
                                "sibling": [
                                    1,
                                    2,
                                    3
                                ],
                                "children": []
                            }
                        ]
                    }
                ]
            }
         ]
       }
    ]