如何将包含Location集合的Group dataclass转换为嵌套字典?
解决Dataclass嵌套集合序列化问题
问题原因
dataclasses.asdict() 默认只会递归处理列表、元组、字典中的dataclass实例,而集合(set)不在它的自动处理范围内。因此当你序列化包含set[Location]的Group实例时,集合里的Location对象会保留为原始实例,不会被转为字典。
解决方案
1. 自定义递归序列化函数
手动实现递归处理逻辑,覆盖集合类型的转换,将集合内的每个dataclass实例转为字典(同时将集合转为列表——因为JSON等常见序列化格式不支持集合类型):
from dataclasses import dataclass, is_dataclass from typing import Set @dataclass class Location: x: int y: int @dataclass class Group: name: str locations: Set[Location] def dataclass_to_dict(obj): if is_dataclass(obj): return {field: dataclass_to_dict(value) for field, value in obj.__dict__.items()} elif isinstance(obj, (set, list, tuple)): return [dataclass_to_dict(item) for item in obj] elif isinstance(obj, dict): return {k: dataclass_to_dict(v) for k, v in obj.items()} else: return obj # 测试 loc1 = Location(1, 2) loc2 = Location(3, 4) group = Group("test_group", {loc1, loc2}) print(dataclass_to_dict(group)) # 输出: {'name': 'test_group', 'locations': [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}]}
2. 给Group类添加自定义序列化方法
直接在Group类中实现to_dict方法,手动遍历集合处理Location实例:
from dataclasses import asdict @dataclass class Group: name: str locations: Set[Location] def to_dict(self): return { "name": self.name, "locations": [asdict(loc) for loc in self.locations] } # 测试 print(group.to_dict()) # 输出: {'name': 'test_group', 'locations': [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}]}
3. 扩展原asdict的处理逻辑(进阶)
复用dataclasses.asdict的核心逻辑,仅修改集合类型的处理规则:
from dataclasses import _asdict_inner, asdict def custom_asdict(obj, *, dict_factory=dict): def inner(obj): if isinstance(obj, set): # 若需保留集合类型可改为 type(obj)(inner(item) for item in obj) return [inner(item) for item in obj] return _asdict_inner(obj, inner) return dict_factory(inner(obj)) # 测试 print(custom_asdict(group)) # 输出: {'name': 'test_group', 'locations': [{'x': 1, 'y': 2}, {'x': 3, 'y': 4}]}
内容的提问来源于stack exchange,提问作者JGG
相关产品推荐
相关产品推荐

