How to make a Python class serializable?
A simple class:
class FileItem:
def __init__(self, fname):
self.fname = fname
What should I do to be able to get output of:
json.dumps()
Without an error (FileItem instance at ... is not JSON serializable
)
jsonweb seems to be the best solution for me. See http://www.jsonweb.info/en/latest/
For more complex classes you could consider the tool jsonpickle:
(link to jsonpickle on PyPi)
I ran into this problem when I tried to store Peewee's model into PostgreSQL
JSONField
.After struggling for a while, here's the general solution.
The key to my solution is going through Python's source code and realizing that the code documentation (described here) already explains how to extend the existing
json.dumps
to support other data types.Suppose you current have a model that contains some fields that are not serializable to JSON and the model that contains the JSON field originally looks like this:
Just define a custom
JSONEncoder
like this:And then just use it in your
JSONField
like below:The key is the
default(self, obj)
method above. For every single... is not JSON serializable
complaint you receive from Python, just add code to handle the unserializable-to-JSON type (such asEnum
ordatetime
)For example, here's how I support a class inheriting from
Enum
:Finally, with the code implemented like above, you can just convert any Peewee models to be a JSON-seriazable object like below:
Though the code above was (somewhat) specific to Peewee, but I think:
json.dumps
works, this solution also works with Python (sans ORM) in general tooAny questions, please post in the comments section. Thanks!
I chose to use decorators to solve the datetime object serialization problem. Here is my code:
By importing the above module, my other modules use json in a normal way (without specifying the default keyword) to serialize data that contains date time objects. The datetime serializer code is automatically called for json.dumps and json.dump.
Here is my 3 cents ...
This demonstrates explicit json serialization for a tree-like python object.
Note: If you actually wanted some code like this you could use the twisted FilePath class.
Most of the answers involve changing the call to json.dumps(), which is not always possible or desirable (it may happen inside a framework component for example).
If you want to be able to call json.dumps(obj) as is, then a simple solution is inheriting from dict:
This works if your class is just basic data representation, for trickier things you can always set keys explicitly.