0

I am setting up some values in a nested JSON. In the JSON, it is not necessary that the keys would always be present.
My sample code looks like below.

if 'key' not in data:
    data['key'] = {}
if 'nested_key' not in data['key']:
    data['key']['nested_key'] = some_value

Is there any other elegant way to achieve this? Simply assigning the value without if's like - data['key']['nested_key'] = some_value can sometimes throw KeyError.

I referred multiple similar questions about "getting nested JSON" on StackOverflow but none fulfilled my requirement. So I have added a new question. In case, this is a duplicate question then I'll remove this one once guided towards the right question.

Thanks

2
  • In case of python dictionary, to retrieve a value for a key we need a key check. But for assigning values to a key, even if the key is not present, a new key will be created. Commented Feb 6, 2019 at 5:23
  • yes but in my case there are nested keys which lead to KeyError if both are absent. Commented Feb 6, 2019 at 5:32

2 Answers 2

3

Please note that, for the insertion you need not check for the key and you can directly add it. But, defaultdict can be used. It is particularly helpful incase of values like lists.

from collections import defaultdict

data = defaultdict(dict)
data['key']['nested_key'] = some_value

defaultdict will ensure that you will never get a key error. If the key doesn't exist, it returns an empty object of the type with which you have initialized it.

List based example:

from collections import defaultdict

data = defaultdict(list)
data['key'].append(1)

which otherwise will have to be done like below:

data = {}
if 'key' not in data:
    data['key'] = ['1']
else:
    data['key'].append('2')

Example based on existing dict:

from collections import defaultdict

data = {'key1': 'sample'}    
data_new = defaultdict(dict,data)    
data_new['key']['something'] = 'nothing'

print data_new

Output:

defaultdict(<type 'dict'>, {'key1': 'sample', 'key': {'something': 'nothing'}})
Sign up to request clarification or add additional context in comments.

4 Comments

The first argument of the defaultdict should be callable or None right? Also when I try defaultdict with nested dict it still gives me KeyError from collections import defaultdict data = {} dic = defaultdict(None, data) dic['something']['new'] = 'hello' KeyError: 'something'
@ManthanJamdagni, Please check my updated answer. It doesn't thrown an error for nested dicts. Use it the way I have done.
Hi @Jay, probably I did not phrase the question very clearly, but I had a dict already which I had to turn into a defaultdict to achieve what I was looking for. So for me the code would be - data1 = defaultdict(dict, data) . Thanks anyway.
@ManthanJamdagni, Sorry, I misunderstood. You are right. Your code would be data1 = defaultdict(dict, data). I have also updated my answer.
2

You can write in one statement:

data.setdefault('key', {})['nested_value'] = some_value

but I am not sure it looks more elegant.

PS: if you prefer to use defaultdict as proposed by Jay, you can initialize the new dict with the original one returned by json.loads(), then passes it to json.dumps():

data2 = defaultdict(dict, data)
data2['key'] = value
json.dumps(data2)    # print the expected dict

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.