支持嵌套类型中自定义类的默认序列化

Posted

技术标签:

【中文标题】支持嵌套类型中自定义类的默认序列化【英文标题】:Support default serialisation for a custom class in a nested type 【发布时间】:2018-08-18 22:31:00 【问题描述】:

我定义了一个类A,并且在其他类、容器和嵌套类型中使用A 的对象。

例子

a = A()
b = [a,3,'hello'
c = 'hey': b, 'huy': 3
d = [a,b,c]

我对@9​​87654325@的json表示很感兴趣,所以我当然要指定遇到A的实例时如何表现。

对于 'A' 类的对象,我想得到这个(注意我跳过了 att2,这表明我不使用 a.__dict__ 之类的东西):


    class_name = 'A',
    att1 = '<value of att1>',
    att3 = '<value of att3>'

att1 可以是任何东西:A 实例、默认类型等。

我希望能够调用 json.dumps(d) 并获得所需的输出,所以我想做的是告诉 A 类在 json 序列化程序询问时要输出什么。

我环顾四周,只发现了复杂的解决方案,其中将 lambda 或类传递给 json.dumps(),但我不明白为什么不直接覆盖由 json 序列化程序调用的方法,例如覆盖 @987654333 时@ 或__repr__()

也许这是不可能的? 在这种情况下,我的情况可能是一个简单的解决方案?请注意,在我的实际问题中,我不仅有 A 类,还有嵌套在一起的各种自定义类,因此覆盖默认序列化程序将是自然且更简单的解决方案。

我的一个尝试

我正在尝试遵循encoder.py第160行的建议

所以从json.JSONEncoder 继承A 并且我声明了方法

def default(self,obj):
    return 'valid custom json representation of A'

但这不起作用,并且引发了上述链接第 179 行的异常。我的代码有什么问题?

【问题讨论】:

【参考方案1】:

默认的 JSON 编码器(您链接到的)只知道如何处理“简单”的东西,如字典、列表、字符串和数字。它没有尝试序列化类,因此没有可以在类上实现的“特殊”方法以使其可序列化为 JSON。基本上,如果你想使用json.dumps,你将不得不传递一些额外的东西才能使它与你的自定义类一起工作。

当编码器不知道如何处理对象时,它会调用default 方法。根据您的问题,我相信您已经发现了这一点,但是您对 default 方法应该去哪里有点困惑。这是一个可以满足您要求的示例:

import json

def default(o):
    if hasattr(o, 'to_json'):
        return o.to_json()
    raise TypeError(f'Object of type o.__class__.__name__ is not JSON serializable')

class A(object):
    def __init__(self):
        self.data = 'stuff'
        self.other_data = 'other stuff'

    def to_json(self):
        return 'data': self.data

a = A()
b = [a, 3, 'hello']
c = 'hey': b, 'huy': 3
d = [a, b, c]

print(json.dumps(d, default=default))

打印出来的:

["data": "stuff", ["data": "stuff", 3, "hello"], "hey": ["data": "stuff", 3, "hello"], "huy": 3]

请注意,现在每个自定义类只需要实现to_json 方法,并且所有内容都会正确序列化(假设您在调用json.dumps 时传递了自定义default 函数)。

【讨论】:

这是我正在寻找的简单答案!谢谢

以上是关于支持嵌套类型中自定义类的默认序列化的主要内容,如果未能解决你的问题,请参考以下文章

flink 中自定义类的 hashCode() 和 equals() 方法

Qt中自定义类的方法

python中自定义函数类的引用(最全)

java中自定义异常为何要继承exception类

基类 派生类 类的继承与约束

Java中自定义类和基本类型声明的数组,在对内存中存储的内容、方式和内存地址指向方面有啥区别?