Coder Perfect

How to construct a JSON serializable class

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 kwarg:, 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, inheriting from dict is an easy approach.

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