So how can we serialize a Python object in a JSON format? Quite easy, you just need to import the JSON module and then use the dumps() and loads() functions: dumps() takes a Python object and returns a string with the result of the JSON serialization process.
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
The json module exposes two methods for serializing Python objects into JSON format. dump() will write Python data to a file-like object. We use this when we want to serialize our Python data to an external JSON file. dumps() will write Python data to a string in JSON format.
The Python "TypeError: Object of type function is not JSON serializable" occurs when we try to serialize a function to JSON. To solve the error, make sure to call the function and serialize the object that the function returns.
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.
You can specify the default
named parameter in the json.dumps()
function:
json.dumps(obj, default=lambda x: x.__dict__)
Explanation:
Form the docs (2.7, 3.6):
``default(obj)`` is a function that should return a serializable version
of obj or raise TypeError. The default simply raises TypeError.
(Works on Python 2.7 and Python 3.x)
Note: In this case you need instance
variables and not class
variables, as the example in the question tries to do. (I am assuming the asker meant class instance
to be an object of a class)
I learned this first from @phihag's answer here. Found it to be the simplest and cleanest way to do the job.
Using jsonpickle
import jsonpickle
object = YourClass()
json_object = jsonpickle.encode(object)
I just do:
data=json.dumps(myobject.__dict__)
This is not the full answer, and if you have some sort of complicated object class you certainly will not get everything. However I use this for some of my simple objects.
One that it works really well on is the "options" class that you get from the OptionParser module. Here it is along with the JSON request itself.
def executeJson(self, url, options):
data=json.dumps(options.__dict__)
if options.verbose:
print data
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
return requests.post(url, data, headers=headers)
JSON is not really meant for serializing arbitrary Python objects. It's great for serializing dict
objects, but the pickle
module is really what you should be using in general. Output from pickle
is not really human-readable, but it should unpickle just fine. If you insist on using JSON, you could check out the jsonpickle
module, which is an interesting hybrid approach.
https://github.com/jsonpickle/jsonpickle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With