我有一个看起来像这样的物体
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
编码器等值添加过滤。但没有用
1条答案
按热度按时间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__
,所以编码器最终会失败。