Python 重写继承的默认支持对象(如dict、list)的嵌套JSON编码
我已经建立了一些自己的类,这些类是从一本字典中子类化的。然而,当我想将它们编码为JSON(使用Python)时,我希望它们以一种可以将它们解码回原始对象而不是dict的方式进行序列化 所以我想支持我自己类的嵌套对象(从dict继承) 我试过这样的东西:Python 重写继承的默认支持对象(如dict、list)的嵌套JSON编码,python,json,encoding,recursion,nested,Python,Json,Encoding,Recursion,Nested,我已经建立了一些自己的类,这些类是从一本字典中子类化的。然而,当我想将它们编码为JSON(使用Python)时,我希望它们以一种可以将它们解码回原始对象而不是dict的方式进行序列化 所以我想支持我自己类的嵌套对象(从dict继承) 我试过这样的东西: class ShadingInfoEncoder(json.JSONEncoder): def encode(self, o): if type(o).__name__ == "NodeInfo":
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)
以及:
它在一般情况下是有效的,但是当它们被嵌套或者第一个被转储的对象不属于这些类型时,它就不起作用了。因此,这仅在输入对象为该类型时有效。但当它嵌套时就不是了
我不知道如何递归编码这个JSON,以便所有嵌套/包含的实例都按照相同的规则编码
我原以为使用JSONECODER的默认方法会更容易(只要对象是不受支持的类型,就会调用该方法)。但是,由于我的对象是从dict继承的,它们会被解析到字典中,而不是通过“默认”方法进行处理。我最后做了以下工作
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
我的解码器被设置为按照(简化和部分代码)的思路进行操作:
NodeInfo解码方法获取输入的字典,并使用它初始化创建和返回的NodeInfo对象的值/属性
更多信息:
也可以在上面看到我的答案
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
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