Python动态字典键序列化:如何映射响应动态键到dataclass类成员
解决方案
核心问题是响应row中的动态键不属于Row类的定义字段,直接传入构造方法会触发意外参数报错。你可以根据需求选择以下两种实现方案:
方案1:从custom_fields提取值映射到固定字段(更稳定)
观察到响应中custom_fields已经包含了所有动态键对应的id和值映射,完全不需要依赖外层的动态键,直接从该字段提取值绑定到x/y即可,外层动态键可以直接忽略:
from dataclasses import dataclass from typing import List @dataclass class Serialisable: @classmethod def from_dict(cls, d): if d is not None: return cls(**d) @dataclass class CustomField(Serialisable): id: int value: str @dataclass class Row(Serialisable): x: str # 对应id 1900000084913的字段值 y: str # 对应id 360018501198的字段值 custom_fields: List[CustomField] @classmethod def from_dict(cls, d): if d is not None: custom_fields_data = d.pop("custom_fields", None) custom_fields = [] if custom_fields_data is not None: custom_fields = [CustomField.from_dict(field) for field in custom_fields_data] # 直接从custom_fields提取对应id的值,完全忽略外层动态键 x = next(field.value for field in custom_fields if field.id == 1900000084913) y = next(field.value for field in custom_fields if field.id == 360018501198) return cls(x=x, y=y, custom_fields=custom_fields) @dataclass class ResponseObject(Serialisable): rows: List[Row] @classmethod def from_dict(cls, d): if d is not None: kwargs = dict(d) rows = kwargs.pop("rows", None) if rows is not None: kwargs["rows"] = [ Row.from_dict(row) for row in rows ] return cls(**kwargs) if __name__ == "__main__": response = { 'rows': [ { '1900000084913': '222222', '360018501198': '4003112', 'custom_fields': [ {'id': 360018501198, 'value': '4003112'}, {'id': 1900000084913, 'value': '222222'} ] } ] } response_obj = ResponseObject.from_dict(response) print(response_obj) # 输出结果:ResponseObject(rows=[Row(x='222222', y='4003112', custom_fields=[CustomField(id=360018501198, value='4003112'), CustomField(id=1900000084913, value='222222')])])
方案2:存储所有动态键到字典(扩展性更强)
如果动态键的数量不固定,后续可能新增,你可以新增一个字段存储所有动态键值对,不需要提前定义固定字段:
@dataclass class Row(Serialisable): dynamic_fields: dict # 存储所有动态键值对 custom_fields: List[CustomField] @classmethod def from_dict(cls, d): if d is not None: d_copy = dict(d) custom_fields_data = d_copy.pop("custom_fields", None) if custom_fields_data is not None: custom_fields = [CustomField.from_dict(field) for field in custom_fields_data] # 剩余的所有键都是动态键,统一存入dynamic_fields dynamic_fields = d_copy return cls(dynamic_fields=dynamic_fields, custom_fields=custom_fields)
后续可以通过row.dynamic_fields['1900000084913']的方式获取对应动态键的值。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

