Problem
How do you serialize a Python class?
A simple class:
class FileItem:
def __init__(self, fname):
self.fname = fname
What should I do to be able to get the following output:
>>> import json
>>> my_file = FileItem('/foo/bar')
>>> json.dumps(my_file)
TypeError: Object of type 'FileItem' is not JSON serializable
Without the error
Asked by Sergey
Solution #1
Here’s a quick fix for a simple feature:
Implement a serializer method instead of a JSON serializable class:
import json
class Object:
def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__,
sort_keys=True, indent=4)
So you simply say “serialize”:
me = Object()
me.name = "Onur"
me.age = 35
me.dog = Object()
me.dog.name = "Apollo"
print(me.toJSON())
will output:
{
"age": 35,
"dog": {
"name": "Apollo"
},
"name": "Onur"
}
Answered by Onur Yıldırım
Solution #2
Do you have any notion what the expected outcome will be? Will this, for example, suffice?
>>> f = FileItem("/foo/bar")
>>> magic(f)
'{"fname": "/foo/bar"}'
You may simply call json.dumps(f. dict ) in such instance.
You’ll need to subclass JSONEncoder and create your own custom serialization if you want more customized output.
See the example below for a simple example.
>>> from json import JSONEncoder
>>> class MyEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
>>> MyEncoder().encode(f)
'{"fname": "/foo/bar"}'
Then, as cls kw, you send this class to the json.dumps() method.
json.dumps(cls=MyEncoder)
If you wish to decode as well, you’ll need to give the JSONDecoder class a specific object hook. Consider the following scenario:
>>> def from_json(json_object):
if 'fname' in json_object:
return FileItem(json_object['fname'])
>>> f = JSONDecoder(object_hook = from_json).decode('{"fname": "/foo/bar"}')
>>> f
<__main__.FileItem object at 0x9337fac>
>>>
Answered by Manoj Govindan
Solution #3
Consider using the tool jsonpickle for more complex classes:
(PyPi link to jsonpickle)
Answered by gecco
Solution #4
The most of the solutions involve modifying the json.dumps() method, which isn’t always viable or acceptable (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:
class FileItem(dict):
def __init__(self, fname):
dict.__init__(self, fname=fname)
f = FileItem('tasks.txt')
json.dumps(f) #No need to change anything here
If your class is only for simple data representation, this works fine; for more complicated situations, you can always assign keys directly.
Answered by andyhasit
Solution #5
I agree with Onur’s response, however I’d add an optional toJSON() function for objects to serialize themselves:
def dumper(obj):
try:
return obj.toJSON()
except:
return obj.__dict__
print json.dumps(some_big_object, default=dumper, indent=2)
Answered by Jason S
Post is based on https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable