How to get a list of dict that each dict is coming from the same original dict with only one key removed?

Question:

My scenario:
I need to iterate through a nested json object, get return a list of json object, each has one key removed. And you don’t know how the original data are structured.

As far as I go:
I wrote a recursion function to print every key value in the object. It works. But this is not what I want.

Define return:
This function gets a dict and returns a list of dict, each dict is a copy of the original dict after one key removed.

If the dict has 3 keys from the beginning, then I should get 3 dicts each has 1 key removed.

And yes if the key has nested value, they should be removed as well. For example if the key happens to be the root key, then it remains an empty dict.

Here’s my code:

def iterate_keys(data: dict):
    # This is as far as I can go
    for key, value in data.items():
        if type(value) in [dict, ]:
            iterate_keys(value)
        elif type(value) in [list, ]:
            for item in value:
                if type(item) in [dict]:
                    iterate_keys(item)
        print(key, value)

# def what_i_really_want(data: dict) -> list:
    # return [dict1, dict2, ...]

if __name__ == '__main__':
    test_dict = {
        "a": "a",
        "c": {
            "c1": [
                {"c11": "c11"},
                {"c12": "c12"},
            ]
        },
    }

    iterate_keys(test_dict)

For the test_dict in the code, ideally it should return list dicts like blow.

result_should_be = [
        {
            # with "a" removed
            "c": {
                "c1": [
                    {"c11": "c11"},
                    {"c12": "c12"},
                ]
            }
        },
        # with "c11" removed
        {
            "a": "a",
            "c": {
                "c1": [
                    {"c12": "c12"},
                ]
            }
        },
        # with "c12" removed
        {
            "a": "a",
            "c": {
                "c1": [
                    {"c11": "c11"},
                ]
            }
        },
        # with "c1" removed
        {
            "a": "a",
            "c": {}
        },
        # with "c" removed
        {
            "a": "a"
        },
    ]

At the end of the day, I’m creating a bunch of test cases.
Hope I made myself clear

Asked By: lulian

||

Answers:

I have really been struggling with this. Somehow I managed to solve it with two libraries.

The first one jsonpathgenerator gets me all the jsonpath of my original data. It orginally gave me all the ‘leaf’ item’s jsonpath. So I changed the source code a little bit to get every key’s jsonpath.

The second one jsonpath_ng let me filter a key with jsonpath.

And with a little bit data manipulation I got the result I was looking for.

This is for if someone ever run into the same situation as me.

Answered By: lulian
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.