Fawzan
Fawzan

Reputation: 4849

Deleting a key from a nested dictionary / json

I am trying to remove an element from a JSON file using python. I have converted the dictionary to a python dictionary and so far I have been failing. JSON file I am working with is uploaded here

I need to delete all the associated keys and value from the JSON if the key is 'access_ip_v4'.

I cannot use sed/grep or any other regex techniques or string replace techniques. I am kind of stuck with python dictionaries on this.

Here is my work so far.

def dict_sweep(input_dic, k):
    for key in input_dic.keys():
        if key == k:
            print("DIRECT DELETE")
            del input_dic[key]
        elif type(input_dic[key]) is dict:
            print('DICT FOUND')
            input_dic[key] = dict_sweep(input_dic[key], k)
        elif isinstance(type(input_dic[key]), type([])):
            print("LIST FOUND")
            for i, v in enumerate(input_dic[key]):
                if isinstance(input_dic[key][i], dict):
                    input_dic[key][i] = dict_sweep(v, k)
    return input_dic

I think my code fails when it encounters a list. Failing in the sense,

clean_data = dict_sweep(data, 'access_ip_v4')
print(clean_data)

will again print the data rather than printing the cleaned version of data.

I am not so sure about it. I have read some other questions like this but It is not helpful. Can someone give me a pointer here?

Upvotes: 2

Views: 3381

Answers (1)

Olivier Melançon
Olivier Melançon

Reputation: 22314

The error

Your error comes from the expression isinstance(type(input_dic[key]), type([])). You want to check if input_dict[key] is a list, not type(input_dic[key]) which is a type.

So replace the last elif statement by this.

elif isinstance(input_dic[key], list):
    print("LIST FOUND")
    ...

A better approach

Although, it is not recommended to delete from the object you are iterating over. In particular, if you are using Python3, the above code will raise RuntimeError: dictionary changed size during iteration. The correct approach is to build a new dictionary without the keys you want to delete.

def dict_sweep(input_dict, key):
    if isinstance(input_dict, dict):
        return {k: dict_sweep(v, key) for k, v in input_dict.items() if k != key}

    elif isinstance(input_dict, list):
        return [dict_sweep(element, key) for element in input_dict]

    else:
        return input_dict

Here is the result.

d = {'delete': 1, 'ok': [{'delete': 1, 'ok': 1}]}
new_d = dict_sweep(d, 'delete') # {'ok': [{'ok': 1}]}

Upvotes: 10

Related Questions