使用classmethods序列化JSON对象

yqkkidmi  于 2023-10-21  发布在  其他
关注(0)|答案(1)|浏览(144)

我有一个看起来像这样的物体

import json
from typing import Any

class Identity:
    def __init__(self, name: str) -> None:
        self.name = name

class BasicEncoder(json.JSONEncoder):
    def default(self, obj: Any) -> Any:
        return obj.__dict__
        
id = Identity(name='Random name')
print(json.dumps(id, cls=BasicEncoder))

这一招很管用。
我决定将classmethod函数添加到Identity对象中,以便拥有类似静态方法的东西,可以将当前对象序列化为json。
我把密码改成了这个

from __future__ import annotations
import json
from typing import Any

class Identity:
    def __init__(self, name: str) -> None:
        self.name = name
        self.permissions = []

    @classmethod
    def to_json(cls: Identity) -> str:
        return json.dumps(cls, cls=BasicEncoder)

class BasicEncoder(json.JSONEncoder):
    def default(self, obj: Any) -> Any:
        return obj.__dict__
    
id = Identity(name='Random name')
print(id.to_json())

但是现在序列化抛出这个错误

'mappingproxy' object has no attribute '__dict__'. Did you mean: '__dir__'

在一个类似的场景中(对于另一个更复杂的对象),我得到了另一个异常

'getset_descriptor' object has no attribute '__dict__'

有什么问题吗?据我所知,它现在正试图用classmethod序列化不仅仅是对象字段。如何解决?
我尝试为__dict__键和classmethod编码器等值添加过滤。但没有用

brtdzjyr

brtdzjyr1#

首先,我对这个问题的背景有点困惑:看起来并不清楚你是在问自定义JSONEncoder的行为,还是你对classmethod/instances有一些一般性的误解,因此你问了错误的问题:这里使用classmethod的意义是什么?您正在从示例调用classmethod,并且似乎您正在尝试序列化类Identity而不是示例id本身。请注意,如示例中所示更改代码并不会实现您提到的“* 允许将当前对象序列化为json*”。
然后谈谈你的自定义JSONEncoder BasicEncoder本身。如果查看内置的class JSONEncoder,那么您将看到您的自定义编码器尝试在第一个实现中迭代编码id.__dict__,这实际上只是class Identity中的属性名称和值。编码{'name': 'Random name'}也很简单,其中dict中的所有内容都是str
在修改后的代码中,情况完全不同,因为现在您正在尝试将class Identity本身(它是类型的示例)序列化为__dict__。如果您手动将__dict__对象查找到任何类中,
然后你会发现Identity.__dict__是一个mappingproxy对象,它不能被你的自定义编码器序列化。
长话短说,您在自定义编码器中的自定义default方法尝试通过其__dict__属性序列化某些内容。然后在代码示例中,编码器首先尝试使用mappingproxy__dict__对其进行编码。由于mappingproxy不是数字/字符串或它们的列表/元组,它将继续尝试通过进一步阅读__dict__来编码mappingproxy。因为mappingproxy没有__dict__,所以编码器最终会失败。

相关问题