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?
Advertisement
Answer
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