maurera
maurera

Reputation: 1659

In Python, how to concisely replace nested values in json data?

This is an extension to In Python, how to concisely get nested values in json data?

I have data loaded from JSON and am trying to replace arbitrary nested values using a list as input, where the list corresponds to the names of successive children. I want a function replace_value(data,lookup,value) that replaces the value in the data by treating each entry in lookup as a nested child.

Here is the structure of what I'm trying to do:

json_data = {'alldata':{'name':'CAD/USD','TimeSeries':{'dates':['2018-01-01','2018-01-02'],'rates':[1.3241,1.3233]}}}

def replace_value(data,lookup,value):
    DEFINITION

lookup = ['alldata','TimeSeries','rates']
replace_value(json_data,lookup,[2,3])

# The following should return [2,3]
print(json_data['alldata']['TimeSeries']['rates'])

I was able to make a start with get_value(), but am stumped about how to do replacement. I'm not fixed to this code structure, but want to be able to programatically replace a value in the data given the list of successive children and the value to replace.

Note: it is possible that lookup can be of length 1

Upvotes: 2

Views: 856

Answers (3)

Patrick Haugh
Patrick Haugh

Reputation: 60944

Follow the lookups until we're second from the end, then assign the value to the last lookup in the current object

def get_value(data,lookup):  # Or whatever definition you like
    res = data
    for item in lookup:
        res = res[item]
    return res

def replace_value(data, lookup, value):
    obj = get_value(data, lookup[:-1])
    obj[lookup[-1]] = value

json_data = {'alldata':{'name':'CAD/USD','TimeSeries':{'dates':['2018-01-01','2018-01-02'],'rates':[1.3241,1.3233]}}}

lookup = ['alldata','TimeSeries','rates']
replace_value(json_data,lookup,[2,3])

print(json_data['alldata']['TimeSeries']['rates']) # [2, 3]

If you're worried about the list copy lookup[:-1], you can replace it with an iterator slice:

from itertools import islice

def replace_value(data, lookup, value):
    it = iter(lookup)
    slice = islice(it, len(lookup)-1)
    obj = get_value(data, slice)
    final = next(it)
    obj[final] = value

Upvotes: 2

Shashank V
Shashank V

Reputation: 11193

Once you have get_value

get_value(json_data, lookup[:-1])[lookup[-1]] = value

Upvotes: 0

blhsing
blhsing

Reputation: 106455

You can obtain the parent to the final sub-dict first, so that you can reference it to alter the value of that sub-dict under the final key:

def replace_value(data, lookup, replacement):
    *parents, key = lookup
    for parent in parents:
        data = data[parent]
    data[key] = replacement

so that:

json_data = {'alldata':{'name':'CAD/USD','TimeSeries':{'dates':['2018-01-01','2018-01-02'],'rates':[1.3241,1.3233]}}}
lookup = ['alldata','TimeSeries','rates']
replace_value(json_data,lookup,[2,3])
print(json_data['alldata']['TimeSeries']['rates'])

outputs:

[2, 3]

Upvotes: 1

Related Questions