Serializing class instance to JSON
I am trying to create a JSON string representation of a class instance and having difficulty. Let's say the class is built like this:
class testclass:
value1 = "a"
value2 = "b"
A call to the json.dumps is made like this:
t = testclass()
json.dumps(t)
It is failing and telling me that the testclass is not JSON serializable.
TypeError: <__main__.testclass object at 0x000000000227A400> is not JSON serializable
I have also tried using the pickle module :
t = testclass()
print(pickle.dumps(t, pickle.HIGHEST_PROTOCOL))
And it gives class instance information but not a serialized content of the class instance.
b'\x80\x03c__main__\ntestclass\nq\x00)\x81q\x01}q\x02b.'
What am I doing wrong?
The basic problem is that the JSON encoder json.dumps()
only knows how to serialize a limited set of object types by default, all built-in types. List here: https://docs.python.org/3.3/library/json.html#encoders-and-decoders
One good solution would be to make your class inherit from JSONEncoder
and then implement the JSONEncoder.default()
function, and make that function emit the correct JSON for your class.
A simple solution would be to call json.dumps()
on the .__dict__
member of that instance. That is a standard Python dict
and if your class is simple it will be JSON serializable.
class Foo(object):
def __init__(self):
self.x = 1
self.y = 2
foo = Foo()
s = json.dumps(foo) # raises TypeError with "is not JSON serializable"
s = json.dumps(foo.__dict__) # s set to: {"x":1, "y":2}
The above approach is discussed in this blog posting:
Serializing arbitrary Python objects to JSON using _dict_
And, of course, Python offers a built-in function that accesses .__dict__
for you, called vars()
.
So the above example can also be done as:
s = json.dumps(vars(foo)) # s set to: {"x":1, "y":2}
There's one way that works great for me that you can try out:
json.dumps()
can take an optional parameter default where you can specify a custom serializer function for unknown types, which in my case looks like
def serialize(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, date):
serial = obj.isoformat()
return serial
if isinstance(obj, time):
serial = obj.isoformat()
return serial
return obj.__dict__
First two ifs are for date and time serialization
and then there is a obj.__dict__
returned for any other object.
the final call looks like:
json.dumps(myObj, default=serialize)
It's especially good when you are serializing a collection and you don't want to call __dict__
explicitly for every object. Here it's done for you automatically.
So far worked so good for me, looking forward for your thoughts.