如何在Python Dataclass中实现序列化与反序列化的字段键映射
使用Python Dataclass实现字段名双向映射的序列化/反序列化
方案一:用Pydantic(推荐)
Pydantic对dataclass有原生支持,通过Field的alias参数可轻松实现字段名的双向映射,该参数同时支持反序列化(输入键映射到类属性)和序列化(类属性转换为指定键名)。
步骤1:安装Pydantic
pip install pydantic
步骤2:定义带别名的Dataclass
用Pydantic的dataclass替代原生版本,通过Field指定别名:
from pydantic.dataclasses import dataclass from pydantic import Field @dataclass class MySchema: account_id: int | None = Field(default=None, alias='accountId', metadata=dict(required=False)) short_key: int | None = Field(default=None, alias='shortKey', metadata=dict(required=False))
步骤3:反序列化(JSON/字典转Dataclass)
直接通过类构造方法传入原始数据即可:
# 原始输入数据 raw_data = {"accountId": 123, "shortKey": 54} # 反序列化 schema = MySchema(**raw_data) print(schema.account_id) # 输出: 123 print(schema.short_key) # 输出: 54
步骤4:序列化(Dataclass转字典/JSON)
使用model_dump()方法并指定by_alias=True,即可输出带别名的键值对:
# 序列化为带别名的字典 serialized_data = schema.model_dump(by_alias=True) print(serialized_data) # 输出: {'accountId': 123, 'shortKey': 54} # 转换为JSON字符串 import json json_str = json.dumps(serialized_data) print(json_str) # 输出: {"accountId": 123, "shortKey": 54}
方案二:原生Dataclass手动实现(无第三方库)
若不想依赖第三方库,可自行编写工具函数处理键名映射:
步骤1:定义原生Dataclass
在metadata中自定义data_key标识映射的字段名:
from dataclasses import dataclass, field, asdict @dataclass class MySchema: account_id: int | None = field(default=None, metadata=dict(required=False, data_key='accountId')) short_key: int | None = field(default=None, metadata=dict(required=False, data_key='shortKey'))
步骤2:编写反序列化函数
将输入字典的键转换为类属性名:
def deserialize_to_schema(raw_data: dict) -> MySchema: # 构建映射关系:data_key → 类属性名 key_map = { field.metadata['data_key']: field.name for field in MySchema.__dataclass_fields__.values() if 'data_key' in field.metadata } # 转换键名并初始化dataclass mapped_data = {key_map[k]: v for k, v in raw_data.items() if k in key_map} return MySchema(**mapped_data) # 测试反序列化 raw_data = {"accountId": 123, "shortKey": 54} schema = deserialize_to_schema(raw_data) print(schema.account_id) # 输出: 123
步骤3:编写序列化函数
将类属性名转换为data_key指定的字段名:
def serialize_from_schema(schema: MySchema) -> dict: # 构建映射关系:类属性名 → data_key key_map = { field.name: field.metadata['data_key'] for field in MySchema.__dataclass_fields__.values() if 'data_key' in field.metadata } # 转换键名并过滤空值 raw_dict = asdict(schema) serialized_data = {key_map[k]: v for k, v in raw_dict.items() if k in key_map and v is not None} return serialized_data # 测试序列化 serialized_data = serialize_from_schema(schema) print(serialized_data) # 输出: {'accountId': 123, 'shortKey': 54}
关于data_key的说明
data_key并非原生Python dataclass的内置参数,它多是marshmallow等第三方库的字段别名配置项。而Pydantic的alias参数完全满足你的双向映射需求,是处理这类场景最简洁的方案。
内容的提问来源于stack exchange,提问作者KZiovas
相关产品推荐
相关产品推荐

