自定义Serialisable类JSON序列化异常及c_make_encoder相关问询
问题解答
1. 为Serialisable类补充内容以支持json.dumps()序列化
Python的JSON模块在使用C实现的c_make_encoder时,只会识别原生dict类型,不会触发Python层面的字典协议方法。要解决无indent参数时的序列化问题,可采用以下几种方案:
方案一:实现__iter__方法
C编码器会通过迭代对象获取键,因此实现__iter__返回可序列化实例变量的键迭代器:
class Serialisable(dict): def __init__(self, **kwargs): super().__init__(**kwargs) # 处理实例变量的逻辑,示例中将传入参数设为实例属性 for k, v in kwargs.items(): setattr(self, k, v) def __iter__(self): # 返回非下划线开头的实例属性键(可根据实际调整过滤规则) return iter(k for k in self.__dict__ if not k.startswith('_'))
方案二:自定义JSON编码器并指定使用
无需修改Serialisable类,调用json.dumps()时通过cls参数指定自定义编码器:
import json class SerialisableEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Serialisable): # 将实例变量转换为字典(过滤规则可自定义) return {k: v for k, v in obj.__dict__.items() if not k.startswith('_')} return super().default(obj) # 使用示例 obj = Serialisable(name="test", value=123) print(json.dumps(obj, cls=SerialisableEncoder))
方案三:覆盖dict的核心方法
让C编码器能通过标准字典方法获取键值对:
class Serialisable(dict): def __init__(self, **kwargs): super().__init__(**kwargs) for k, v in kwargs.items(): setattr(self, k, v) def keys(self): return (k for k in self.__dict__ if not k.startswith('_')) def items(self): return ((k, self.__dict__[k]) for k in self.__dict__ if not k.startswith('_')) def __getitem__(self, key): return self.__dict__[key]
2. c_make_encoder的代码位置
c_make_encoder是CPython中JSON模块的C扩展实现,对应的代码位于Python源代码的Modules/_json.c文件中。具体逻辑在PyMakeEncoder函数(对应Python层的c_make_encoder)以及encode_dict函数内,你可以查看对应CPython版本的_json.c文件找到相关实现。
内容的提问来源于stack exchange,提问作者Nuno
相关产品推荐
相关产品推荐

