skip to Main Content

Let´s say we have a database and there is a json stored as a string which contains configurations.
In the application we want to update only a specific value and write then back the json as a string to the database.

The HTTP request provides a "jsonPath" which reflects a path in the json file to navigate to the object we want to update. This parameter is supplied as a list.

An example for the path could be something like [‘input’, ‘keyboard’, ‘language’] and the value we want to set is ‘en’

Here we load the configuration from the database which works so far:

if request.data['jsonPath']: 
    config =  json.loads(models.Config.objects.get(name__startswith='general').value

Then config is just a normal object now, which I can access with the dot notation like config.input.keyboard.language and it contains then the according part in json syntax.

I am able to read out the value of the field with the following syntax:

config[request.data['jsonPath'][0]][request.data['jsonPath'][1]][request.data['jsonPath'[3]]

But the number of parameters can vary and I want also to write it back into the config object, convert it back to a string and write it into the database.

I know it is not a nice thing but I would be interessted how it can be done like this

2

Answers


  1. Assuming you have a nested json object like this:

    mydict = {
        'key1': {
            'key2': {
                'key3': {
                    'foo': 'bar'
                },
            },
        },
    }
    

    And you have a "path" list like this:

    path = ['key1', 'key2', 'key3']
    

    You can traverse the path like this:

    data = mydict
    for key in path:
        data = data[key]
    

    data will end up as the value of the last item in path, in this case the subdict {'foo': 'bar'}

    Login or Signup to reply.
  2. You can use functools.reduce for this:

    functools.reduce(dict.get, path, data)
    

    from functools import reduce
    
    data = {'key1': {'key2': {'key3': {'foo': 'bar'}}}}
    path = ['key1', 'key2', 'key3']
    
    reduce(dict.get, path, data)["foo"] = baz
    

    Result:

    {'key1': {'key2': {'key3': {'foo': 'baz'}}}}
    

    P.S

    If the data type of data is something else you could possibly use operator.itemgetter

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search