覆盖继承的默认支持对象(如 dict、list)的嵌套 JSON 编码 [英] Overriding nested JSON encoding of inherited default supported objects like dict, list

查看:21
本文介绍了覆盖继承的默认支持对象(如 dict、list)的嵌套 JSON 编码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经建立了一些我自己的类,这些类是从字典中继承的来像它们一样工作.然而,当我想将它们编码为 JSON(使用 Python)时,我希望它们以一种可以将它们解码回原始对象而不是 dict 的方式进行序列化.

I've set up some classes of my own that are subclassed from a dictionary to act like them. Yet when I want to encode them to JSON (using Python) I want them to be serialized in a way that I can decode them back to the original objects instead of to a dict.

所以我想支持我自己的类的嵌套对象(从 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)

它在一般情况下有效,但当它们嵌套或被转储的第一个对象不是这些类型时则无效.因此,这仅在输入对象属于该类型时才有效.但在嵌套时则不然.

It works in general, yet not when they are nested or the first object getting dumped is not of those types. Thus this only works when the input object is of that type. Yet not when it's nested.

我不确定如何递归地编码这个 JSON,所以所有嵌套/包含的实例都根据相同的规则进行编码.

I'm not sure how to encode this JSON recursively so all nested/contained instances are encoded according to the same rules.

我认为使用 JSONEncoder 的默认方法会更容易(因为当对象是不受支持的类型时就会调用它.)然而,由于我的对象是从 dict 继承的,它们被解析为字典而不是由默认"方法.

I thought it would be easier to the use the JSONEncoder's default method (as that gets called whenever an object is of an unsupported type.) Yet since my objects are inherited from dict they get parsed to dictionaries instead of being process by the 'default' method.

推荐答案

我最终做了以下事情.

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

我认为这不是最好的方法,但我在这里分享它,看看是否有其他人可以告诉我我做错了什么并向我展示了最好的方法!

I assume this is not the best way to do this, yet I'm sharing it here to see if anyone else can tell me what I'm doing wrong and show me the best way to do this!

请注意,我使用嵌套元组而不是字典,因为我想保持它们列出的顺序,这样我就可以 - 在本例中 - 如果 ShaderInfo 是从 NodeInfo 继承的对象,我可以将 ShaderInfo 覆盖为 _NodeInfo.

Note that I'm using nested tuples instead of a dictionary because I wanted to keep the order they were listed so I could - in this example - override ShaderInfo becoming _NodeInfo if ShaderInfo was an object that inherited from NodeInfo.

我的解码器设置为按照(简化和部分代码)执行某些操作:

My decoder is set up to do something along the lines of (simplified and part of code):

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 对象的值/属性.

The nodeInfoDecode methods gets the entered dictionary and uses it to initialize the values/attributes of the NodeInfo object that gets created and returned.

更多信息:

另请参阅我对 如何更改可序列化 python 对象的 json 编码行为的回答?

这篇关于覆盖继承的默认支持对象(如 dict、list)的嵌套 JSON 编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆