I have a class defined like this
class A:
def __init__(self):
self.item1 = None
def __repr__(self):
return str(self.__dict__)
when I do:
>>> import simplejson
>>> myA = A()
>>> simplejson.dumps(myA)
TypeError: {'item1': None} is not JSON serializable
I can't find the reason why.
Do I need to add any particular method to A for simplejson to serialize my class object?
You can't serialize arbitrary objects with simplejson
. You need to pass a default
and object_hook
to dump
and load
. Here's an example:
class SerializerRegistry(object):
def __init__(self):
self._classes = {}
def add(self, cls):
self._classes[cls.__module__, cls.__name__] = cls
return cls
def object_hook(self, dct):
module, cls_name = dct.pop('__type__', (None, None))
if cls_name is not None:
return self._classes[module, cls_name].from_dict(dct)
else:
return dct
def default(self, obj):
dct = obj.to_dict()
dct['__type__'] = [type(obj).__module__,
type(obj).__name__]
return dct
registry = SerializerRegistry()
@registry.add
class A(object):
def __init__(self, item1):
self.item1 = item1
def __repr__(self):
return str(self.__dict__)
def to_dict(self):
return dict(item1=self.item1)
@classmethod
def from_dict(cls, dct):
return cls(**dct)
s = json.dumps(A(1), default=registry.default)
a = json.loads(s, object_hook=registry.object_hook)
This results in this:
>>> s
'{"item1": 1, "__type__": ["__main__", "A"]}'
>>> a
{'item1': 1}
But what you really need is a function default
that creates dictionary from the objects that you wish to serialize, and a function object_hook
that returns an object (of the correct type) when it is given a dictionary if a dictionary isn't enough. The best approach is to have methods on the serializable classes that create a dict from the object and that construct it back, and also to have a mapping that recognizes to which class the dictionaries belong.
You can also add an identifier to the classes to be used as an index for _classes
. This way you wouldn't have issues if you have to move a class.
According to the json module docs (simplejson was adopted as json in Python 2.6), you need to extend the json.JSONEncoder
class, overriding its default method to translate your object into a type that can be serialised. There doesn't appear to be a method that it looks for on your object.