Pythonオブジェクトをjsonモジュールでjsonにシリアライズ

前の記事で書いたjsonリアライザの仕組みを、自作のパーサではなくjsonモジュールで実装した。32行で実装できた。お手軽。ユーザ定義型のシリアライズの方法は同じで、__encode_json__で永続化したいオブジェクトを返して、__decode_json__クラスメソッドで復元したクラスを返す。あとobjectオブジェクトを継承する。

# coding: utf-8
import json

def object_hooker_factory(clslist):
    clsnamelist = [cls.__name__ for cls in clslist]
    def object_hook(dic):
        if "__class__" in dic and dic["__class__"] in clsnamelist:
            cls = clslist[clsnamelist.index(dic["__class__"])]
            return cls.__decode_json__(dic["__value__"])
        return dic
    return object_hook

class Serializer(json.JSONEncoder):
    def default(self, obj):
        if not type(obj) in [int, float, str, unicode, list, dict]:
            value = eval(self.encode(obj.__encode_json__()))
            name = obj.__class__.__name__
            return {"__class__": name, "__value__": value}
        return json.JSONEncoder.default(self, obj)

def loads(s, clslist=[]):
    object_hook = object_hooker_factory(clslist)
    return json.loads(s, object_hook=object_hook)

def load(fp, clslist=[]):
    return loads(fp.read(), clslist)

def dumps(obj):
    return json.dumps(obj, cls=Serializer)

def dump(fp, obj):
    fp.write(dumps(obj))

"""
# sample

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __repr__(self):
        return "(%.2f, %.2f)" % (self.x, self.y)
    def __encode_json__(self):
        return [self.x, self.y]
    @classmethod
    def __decode_json__(cls, lst):
        return cls(*lst)

class Rectangle(object):
    def __init__(self, p, q):
        self.p = p
        self.q = q
    def __repr__(self):
        return "<Point %s %s>" % (self.p, self.q)
    def __encode_json__(self):
        return [self.p, self.q]
    @classmethod
    def __decode_json__(cls, lst):
        return cls(*lst)

p = Point(0, 1)
q = Point(5, 6)
r = Rectangle(p, q)

print dumps(p)
print dumps(r)
print loads(dumps(p), [Point,Rectangle])
print loads(dumps(r), [Point,Rectangle])
"""

シリアライズする際に何度もevalってるのを短くできると速くなると思う。