7

私はこのように定義されたクラスを持っています

class A:
    def __init__(self):
        self.item1 = None
    def __repr__(self):
        return str(self.__dict__)

私がする時:

>>> import simplejson
>>> myA = A()
>>> simplejson.dumps(myA)
TypeError: {'item1': None} is not JSON serializable

理由がわかりません。

クラス オブジェクトをシリアル化するために、simplejson の A に特定のメソッドを追加する必要がありますか?

4

2 に答える 2

10

を使用して任意のオブジェクトをシリアル化することはできませんsimplejsondefaultaとobject_hooktodumpとを渡す必要があり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。このようにして、クラスを移動する必要がある場合でも問題は発生しません。

于 2011-01-27T21:29:24.857 に答える
3

json モジュールのドキュメント(simplejson は Python 2.6 で json として採用されました) によると、json.JSONEncoderクラスを拡張し、デフォルトのメソッドをオーバーライドして、オブジェクトをシリアル化できる型に変換する必要があります。オブジェクトで検索するメソッドがないようです。

于 2011-01-27T21:20:53.790 に答える