Search code examples
pythonjsondictionarynested

Change value of python nested dictionary with variable path?


How can I pass a dictionary path as an argument? I thought maybe it had something to do with *args or **kwargs but I didn't understand how to use them for this

dictionary = {
    'key1': {
        'attribute1': 'green',
    },
    'attribute2': 5
}
def SaveToFile(target, value):
    with open('savefile.json', 'r') as savefile:
        dictionary = json.load(savefile)

    dictionary[target] = value

    with open('savefile.json', 'w') as savefile:
        json.dump(dictionary, savefile)

SaveToFile('["key1"]["attribute1"]', 'blue')
SaveToFile('["attribute2"]', 10)
print(dictionary)

desired output:

{
    'key1': {
        'attribute1': 'blue'
    },
    'attribute2': 10
}



Solution

  • use regex and recursion to solve this

    dictionary = {
        'key1': {
            'attribute1': 'green',
        },
        'attribute2': 5
    }
    import re
    
    def update_dict(d_, val, *keys):
        if not keys:
            return {}
        key = keys[0]
        
        if isinstance(d_[key], dict):
            d_[key].update(update_dict(d_[key], val, *keys[1:]))
        else:
            if key in d_:
                d_[key]= val
        return d_
        
    
    def ChangeValue(target, value):
        keys = filter(lambda x: bool(x), re.split('\[\"(.*?)\"\]', target))
        update_dict(dictionary, value, *keys)
    
    
    ChangeValue('["key1"]["attribute1"]', 'blue')
    ChangeValue('["attribute2"]', 10)
    dictionary
    # output {'key1': {'attribute1': 'blue'}, 'attribute2': 10}