I am working on a project and need to make use of UserDict instead of dict. I am importing a JSON file that is a dictionary with lists containing more dictionaries.
Here is some example code and the behavior differences I am seeing:
import json
from collections import UserDict
import pprint
person_string = '{"name" : "Bob", \
"age" : 25, \
"addresses":[{"city" : "Greenville", "state" : "NC" }, \
{"city" : "Whiteville", "state" : "NC" }]}'
# dict Example
person_dict = json.loads(person_string)
addresses = person_dict['addresses']
addr_1 = addresses[0]
print(addr_1)
print("\n")
# Add street to the first city entry
addr_1['street'] = "123 The Road"
print(addr_1)
print("\n")
pprint.pprint(person_dict)
print("\n")
# UserDict Example
person_user_dict = UserDict(json.loads(person_string))
user_addresses = person_user_dict['addresses']
user_addr_1 = UserDict(user_addresses[0])
print(user_addr_1)
print("\n")
# Add street to the first city entry
user_addr_1['street'] = "123 The Road"
print(user_addr_1)
print("\n")
pprint.pprint(person_user_dict)
The output:
# Dictionary Example
{'city': 'Greenville', 'state': 'NC'}
{'city': 'Greenville', 'state': 'NC', 'street': '123 The Road'}
{'name': 'Bob',
'age': 25,
'addresses': [{'city': 'Greenville', 'state': 'NC', 'street': '123 The Road'},
{'city': 'Whiteville', 'state': 'NC'}]}
# UserDict Example
{'city': 'Greenville', 'state': 'NC'}
{'city': 'Greenville', 'state': 'NC', 'street': '123 The Road'}
{'name': 'Bob',
'age': 25,
'addresses': [{'city': 'Greenville', 'state': 'NC'}, <---- The 'street' is missing
{'city': 'Whiteville', 'state': 'NC'}]}
Why did the new key not get added to person_user_dict and how can I get UserDict to behave the same way as a dictionary?
CodePudding user response:
Because you created a new dictionary here:
user_addr_1 = UserDict(user_addresses[0])
This isn't unexpected at all, indeed, this is how dict
works. You would see the same exact behavior if you did:
user_addr_1 = dict(user_addresses[0])
You would need to recursively convert all the dict's to UserDict
objects instead. But actually, you just want to use the object_pairs_hook
for the json decoder:
In [3]: import json
...: from collections import UserDict
...:
...: person_string = '{"name" : "Bob", \
...: "age" : 25, \
...: "addresses":[{"city" : "Greenville", "state" : "NC" }, \
...: {"city" : "Whiteville", "state" : "NC" }]}'
In [4]: person_dict = json.loads(person_string, object_pairs_hook=UserDict)
In [5]: person_dict
Out[5]: {'name': 'Bob', 'age': 25, 'addresses': [{'city': 'Greenville', 'state': 'NC'}, {'city': 'Whiteville', 'state': 'NC'}]}
In [6]: type(person_dict)
Out[6]: collections.UserDict
In [7]: type(person_dict['addresses'][0])
Out[7]: collections.UserDict