Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method to serialize custom object to JSON in Python

Tags:

python

json

Generally, we can define __str__ method to make str(obj) return what we want.

But now I want to define my Model object to return a default JSON string when using json.dumps(obj).

Is there any nice way for me to declare a method in the class to do this?

class MyClass:
    ...
    def __json__(self):
        return {'name': self.name, 'age': self.age}

obj = MyClass()

json.dumps(obj) # returns the same as json.dumps(obj.__json__)
like image 560
Alfred Huang Avatar asked Jun 04 '14 06:06

Alfred Huang


2 Answers

If you only need Python -> JSON, it's simple to write a JSONEncoder class that calls such a method for any object:

class AutoJSONEncoder(JSONEncoder):
    def default(self, obj):
        try:
            return obj._json()
        except AttributeError:
            return JSONEncoder.default(self, obj)

You can then use the class directly AutoJSONEncoder().encode(obj) or through the dumps interface json.dumps(obj, cls=AutoJSONEncoder).

The reverse direction requires at least a list of classes for which to call a _fromjson method.

(Note: __foo__ names are reserved so you shouldn't define them for your own purposes. __bar invokes name mangling, which probably isn't what you want.)

like image 99
otus Avatar answered Sep 19 '22 15:09

otus


import json


class MyEncoder(json.JSONEncoder):
    """
    JSONEncoder subclass that leverages an object's `__json__()` method,
    if available, to obtain its default JSON representation. 

    """
    def default(self, obj):
        if hasattr(obj, '__json__'):
            return obj.__json__()
        return json.JSONEncoder.default(self, obj)


class MyClass(object):
    name = 'John'
    age = 30

    def __json__(self):
        return {'name': self.name, 'age': self.age}

>>> json.dumps(MyClass(), cls=MyEncoder)
{"age": 30, "name": "John"}
like image 35
Jakub Roztocil Avatar answered Sep 17 '22 15:09

Jakub Roztocil