I'm trying to serialize a list of python objects with JSON (using simplejson) and am getting the error that the object "is not JSON serializable".
The class is a simple class having fields that are only integers, strings, and floats, and inherits similar fields from one parent superclass, e.g.:
class ParentClass:
def __init__(self, foo):
self.foo = foo
class ChildClass(ParentClass):
def __init__(self, foo, bar):
ParentClass.__init__(self, foo)
self.bar = bar
bar1 = ChildClass(my_foo, my_bar)
bar2 = ChildClass(my_foo, my_bar)
my_list_of_objects = [bar1, bar2]
simplejson.dump(my_list_of_objects, my_filename)
where foo, bar are simple types like I mentioned above. The only tricky thing is that ChildClass sometimes has a field that refers to another object (of a type that is not ParentClass or ChildClass).
What is the easiest way to serialize this as a json object with simplejson? Is it sufficient to make it serializable as a dictionary? Is the best way to simply write a dict method for ChildClass? Finally, does having the field that refer to another object significantly complicate things? If so, I can rewrite my code to only have simple fields in classes (like strings/floats etc.)
thank you.
I feel a bit silly about my possible 2 solutions rereading it now, of course when you use django-rest-framework, this framework have some excellent features buildin for this problem mentioned above.
see this model view example on their website
If you're not using django-rest-framework, this can help anyway:
I found 2 helpfull solutions for this problem in this page: (I like the second one the most!)
Possible solution 1 (or way to go): David Chambers Design made a nice solution
I hope David does not mind I copy paste his solution code here:
Define a serialization method on the instance's model:
and he even extracted the method above, so it's more readable:
Please mind, it's not my solution, all the credits goes to the link included. Just thought this should be on stack overflow.
This could be implemented in the answers above as well.
Solution 2:
My preferable solution is found on this page:
http://www.traddicts.org/webdevelopment/flexible-and-simple-json-serialization-for-django/
By the way, i saw the writer of this second and best solution: is on stackoverflow as well:
Selaux
I hope he sees this, and we can talk about starting to implement and improve his code in an open solution?
As specified in python's JSON docs //
help(json.dumps)
// >You should simply override the
default()
method ofJSONEncoder
in order to provide a custom type conversion, and pass it ascls
argument.Here is one I use to cover Mongo's special data types (datetime and ObjectId)
Calling it as simple as
This is kind of hackish and I'm sure there's probably a lot that can be wrong with it. However, I was producing a simple script and I ran the issue that I did not want to subclass my json serializer to serialize a list of model objects. I ended up using list comprehension
Let: assets = list of modelobjects
Code:
So far seems to have worked charmingly for my needs
If you are using Django, it can be easily done via Django's serializers module. More info can be found here: https://docs.djangoproject.com/en/dev/topics/serialization/
An instance of a custom class could be represented as JSON formatted string with help of following function:
This function will produce JSON-formatted string for
an instance of a custom class,
a dictionary that have instances of custom classes as leaves,
I've used this strategy in the past and been pretty happy with it: Encode your custom objects as JSON object literals (like Python
dict
s) with the following structure:That's essentially a one-item
dict
whose single key is a special string that specifies what kind of object is encoded, and whose value is adict
of the instance's attributes. If that makes sense.A very simple implementation of an encoder and a decoder (simplified from code I've actually used) is like so:
In this implementation assumes that the objects you're encoding will have a
from_dict()
class method that knows how to take recreate an instance from adict
decoded from JSON.It's easy to expand the encoder and decoder to support custom types (e.g.
datetime
objects).EDIT, to answer your edit: The nice thing about an implementation like this is that it will automatically encode and decode instances of any object found in the
TYPES
mapping. That means that it will automatically handle a ChildClass like so:That should result in JSON something like the following: