如何在Pydantic中通用实现字符串/列表字段自动转列表的反序列化逻辑?
自动实现字符串/逗号分隔字符串转列表的Pydantic字段注解
需求背景
我们有手工编辑的YAML配置,其中字段支持三种格式:
- 单个字符串(如
foo: red) - 逗号分隔的字符串(如
bar: red, green) - 标准YAML列表(如
qaz: [red, green, blue]或多行列表)
需要将这些字段统一反序列化为Python列表格式,且希望通过字段注解自动触发转换逻辑,无需在每个模型中重复编写model_post_init代码。
解决方案:自定义Pydantic验证器+Annotated注解
利用Pydantic的BeforeValidator和Annotated组合,结合已实现的process_composite_list函数,创建可复用的字段注解。
步骤1:完善转换函数
确保process_composite_list能处理所有输入场景:
def process_composite_list(value): if isinstance(value, list): return value elif isinstance(value, str): # 分割逗号并去除元素前后空格,过滤空字符串 return [item.strip() for item in value.split(',') if item.strip()] # 非支持类型抛出错误(可根据需求调整为返回空列表) raise ValueError("Unsupported value type for composite list")
步骤2:创建可复用的注解类型
用Annotated封装转换逻辑,形成通用注解:
from typing import Annotated, List from pydantic import BaseModel, BeforeValidator # 定义通用复合列表注解,直接在模型字段中引用 CompositeList = Annotated[List[str], BeforeValidator(process_composite_list)]
步骤3:在模型中使用注解
无需编写model_post_init,直接标注字段类型即可:
class ExampleModel(BaseModel): foo: CompositeList bar: CompositeList qaz: CompositeList class RootModel(BaseModel): examples: ExampleModel
步骤4:测试反序列化
加载YAML配置验证结果:
import yaml # 加载目标YAML内容 yaml_content = """ examples: foo: red bar: red, green qaz: - red - green - blue """ data = yaml.safe_load(yaml_content) model = RootModel(**data) # 输出转换后的结果 print(model.model_dump())
输出结果符合预期:
{ "examples": { "foo": ["red"], "bar": ["red", "green"], "qaz": ["red", "green", "blue"] } }
扩展说明
- 若需支持其他数据类型(如整数列表),可修改
process_composite_list并创建对应注解(如CompositeIntList) - 若使用Pydantic v1,可通过
@validator(pre=True)装饰器实现类似逻辑,但Annotated方式在v2中更简洁灵活
内容的提问来源于stack exchange,提问作者Tamás Szelei
相关产品推荐
相关产品推荐

