を使用して任意のオブジェクトをシリアル化することはできませんsimplejson
。default
aとobject_hook
todump
とを渡す必要がありload
ます。次に例を示します。
class SerializerRegistry(object):
def __init__(self):
self._classes = {}
def add(self, cls):
self._classes[cls.__module__, cls.__name__] = cls
return cls
def object_hook(self, dct):
module, cls_name = dct.pop('__type__', (None, None))
if cls_name is not None:
return self._classes[module, cls_name].from_dict(dct)
else:
return dct
def default(self, obj):
dct = obj.to_dict()
dct['__type__'] = [type(obj).__module__,
type(obj).__name__]
return dct
registry = SerializerRegistry()
@registry.add
class A(object):
def __init__(self, item1):
self.item1 = item1
def __repr__(self):
return str(self.__dict__)
def to_dict(self):
return dict(item1=self.item1)
@classmethod
def from_dict(cls, dct):
return cls(**dct)
s = json.dumps(A(1), default=registry.default)
a = json.loads(s, object_hook=registry.object_hook)
これにより、次のようになります。
>>> s
'{"item1": 1, "__type__": ["__main__", "A"]}'
>>> a
{'item1': 1}
しかし、本当に必要なのは、default
シリアル化するオブジェクトからディクショナリを作成する関数とobject_hook
、ディクショナリが十分でない場合にディクショナリが与えられたときに(正しいタイプの)オブジェクトを返す関数です。最良のアプローチは、オブジェクトからdictを作成し、それを元に戻すシリアル化可能なクラスのメソッドを用意し、辞書がどのクラスに属しているかを認識するマッピングを用意することです。
のインデックスとして使用するクラスに識別子を追加することもできます_classes
。このようにして、クラスを移動する必要がある場合でも問題は発生しません。