9

辞書からサブクラス化して、それらのように動作する独自のクラスをいくつか設定しました。それでも、(Python を使用して) JSON にエンコードする場合は、辞書ではなく元のオブジェクトにデコードできるようにシリアル化する必要があります。

したがって、自分のクラスのネストされたオブジェクト (dict から継承されたもの) をサポートしたいと考えています。

私は次のようなものを試しました:

class ShadingInfoEncoder(json.JSONEncoder):
    def encode(self, o):
        if type(o).__name__ == "NodeInfo":
            return '{"_NodeInfo": ' + super(ShadingInfoEncoder, self).encode(o) + '}'
        elif type(o).__name__ == "ShapeInfo":
            return '{"_ShapeInfo": ' + super(ShadingInfoEncoder, self).encode(o) + '}'
        elif type(o).__name__ == "ShaderInfo":
            return '{"_ShaderInfo": ' + super(ShadingInfoEncoder, self).encode(o) + '}'

        return super(ShadingInfoEncoder, self).encode(o)

と:

class ShadingInfoEncoder(json.JSONEncoder):
    def encode(self, o):
        if isinstance(o, NodeInfo):
            return '{"_NodeInfo": ' + super(ShadingInfoEncoder, self).encode(o) + '}'
        elif isinstance(o, ShapeInfo):
            return '{"_ShapeInfo": ' + super(ShadingInfoEncoder, self).encode(o) + '}'
        elif isinstance(o, ShaderInfo):
            return '{"_ShaderInfo": ' + super(ShadingInfoEncoder, self).encode(o) + '}'

        return super(ShadingInfoEncoder, self).encode(o)

一般的には機能しますが、ネストされている場合、またはダンプされる最初のオブジェクトがそれらのタイプではない場合は機能しません。したがって、これは入力オブジェクトがそのタイプの場合にのみ機能します。ただし、ネストされている場合はそうではありません。

この JSON を再帰的にエンコードする方法がわからないため、ネストされた/含まれるすべてのインスタンスが同じルールに従ってエンコードされます。

JSONEncoder のデフォルト メソッドを使用する方が簡単だと思いました (オブジェクトがサポートされていないタイプの場合は常に呼び出されます)。しかし、私のオブジェクトは dict から継承されているため、「デフォルト」で処理されるのではなく、辞書に解析されます。方法。

4

1 に答える 1

2

私は最終的に次のことをしました。

class ShadingInfoEncoder(json.JSONEncoder):
    def _iterencode(self, o, markers=None):
        jsonPlaceholderNames = (("_ShaderInfo", ShaderInfo),
                            ("_ShapeInfo", ShapeInfo),
                            ("_NodeInfo", NodeInfo))
        for jsonPlaceholderName, cls in customIterEncode:
            if isinstance(o, cls):
                yield '{"' + jsonPlaceholderName+ '": '
                for chunk in super(ShadingInfoEncoder, self)._iterencode(o, markers):
                    yield chunk
                yield '}'
                break
        else:
            for chunk in super(ShadingInfoEncoder, self)._iterencode(o, markers):
                yield chunk

これは最善の方法ではないと思いますが、ここで共有して、他の誰かが私が間違っていることを教えてくれるかどうかを確認し、これを行うための最良の方法を教えてくれます!

リストされている順序を維持したかったので、辞書の代わりにネストされたタプルを使用していることに注意してください。この例では、ShaderInfo が NodeInfo から継承されたオブジェクトである場合、ShaderInfo をオーバーライドして _NodeInfo にすることができます。

私のデコーダーは、(簡略化されたコードの一部)の行に沿って何かを行うように設定されています。

class ShadingInfoDecoder(json.JSONDecoder):
    def decode(self, obj):
        obj = super(ShadingInfoDecoder,self).decode(s)
        if isinstance(obj, dict):
            decoders = [("_set",self.setDecode),
                        ("_NodeInfo", self.nodeInfoDecode),
                        ("_ShapeInfo", self.shapeInfoDecode),
                        ("_ShaderInfo", self.shaderInfoDecode)]
            for placeholder, decoder in decoders:
                if placeholder in obj:
                    return decoder(obj[placeholder])
                else:
                    for k in obj:
                        obj[k] = self.recursiveDecode(obj[k])
        elif isinstance(obj, list):
            for x in range(len(obj)):
                obj[x] = self.recursiveDecode(obj[x])

        return obj

    def setDecode(self, v):
        return set(v)

    def nodeInfoDecode(self, v):
        o = NodeInfo()
        o.update(self.recursiveDecode(v))
        return o

    def shapeInfoDecode(self, v):
        o = ShapeInfo()
        o.update(self.recursiveDecode(v))
        return o

    def shaderInfoDecode(self, v):
        o = ShaderInfo()
        o.update(self.recursiveDecode(v))
        return o

nodeInfoDecode メソッドは、入力された辞書を取得し、それを使用して、作成されて返される NodeInfo オブジェクトの値/属性を初期化します。

より詳しい情報:

また、シリアル化可能な python オブジェクトの json エンコーディング動作を変更する方法に関する私の回答も参照してください。

于 2013-05-03T16:28:44.637 に答える