I have seen several different implementations of a "DictObj" class in Python. That is, a Python object that supports all the operations available for a standard dictionary, but also the ability to get/set items using the .attribute syntax. In recent projects, I have been using an implementation of this as a result object, which I occasionally need to serialize into a JSON string.
I finally decided to write my own class to support all the features I needed. Below is my custom DictObj class:
import pickle
import json
import yaml
class DictObj(dict):
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __getattr__(self, key):
try:
return self.__getitem__(key)
except KeyError:
raise AttributeError(key)
def __delattr__(self, key):
try:
self.__delitem__(key)
except KeyError:
raise AttributeError(key)
def serialize(self, method, indent=None, flow=None):
if method == 'json':
return json.dumps(dict(self), indent=indent)
elif method == 'yaml':
return yaml.dump(dict(self), default_flow_style=flow)
elif method == 'pickle':
return pickle.dumps(self)
def json(self, **kwargs):
return self.serialize('json', **kwargs)
def yaml(self, **kwargs):
return self.serialize('yaml', **kwargs)
def pickle(self, **kwargs):
return self.serialize('pickle', **kwargs)
This implementation retains all the properties of standard dictionary objects, and maps all __***attr__ methods to the dictionary items.
General Usage:
>>> test = DictObj({'one': 1, 'two': 2, 'three': 3})
>>> test.four = 4
>>> test['five'] = 5
>>> test
{'four': 4, 'one': 1, 'five': 5, 'three': 3, 'two': 2}
>>> test.copy()
{'four': 4, 'five': 5, 'three': 3, 'two': 2, 'one': 1}
Serialization:
>>> test.json()
'{"four": 4, "five": 5, "three": 3, "two": 2, "one": 1}'
>>> test.json(indent=4)
'{\n "four": 4, \n "five": 5, \n "three": 3, \n "two": 2, \n "one": 1\n}'
>>> test.yaml()
'{five: 5, four: 4, one: 1, three: 3, two: 2}\n'
>>> test.yaml(flow=False)
'five: 5\nfour: 4\none: 1\nthree: 3\ntwo: 2\n'
>>> test.pickle()
"ccopy_reg\n_reconstructor\np0\n(cDictObj\nDictObj\np1\nc__builtin__\ndict\np2\n(dp3\nS'four'\np4\nI4\nsS'five'\np5\nI5\nsS'three'\np6\nI3\nsS'two'\np7\nI2\nsS'one'\np8\nI1\nstp9\nRp10\n."