Skip to content
Advertisement

Unexpected UserDict Behavior

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
Advertisement