You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pydantic将单值字段统一解析为列表?

使用Pydantic统一解析单值/数组类型的配置字段

问题场景

我有一个需要解析配置的应用,配置字段可能是单个值或数组,例如YAML格式:

fruit: apple
vegetable:
  - tomato
  - cucumber

希望解析后内部统一将fruit处理为['apple'],vegetable保持['tomato', 'cucumber'],且需满足以下要求:

  • 类型检查(mypy)和运行时,字段类型均为list[str](或对应类型的列表)
  • 多类使用时,每个字段最多一行声明
  • 方案可推广至任意类型,不限于字符串

已尝试方案的不足

  • fruit: Union[str, list[str]]:使用时需处处检查类型,违背统一解析的初衷
  • 每个字段单独写@validator("fruit", pre=True):重复代码多,每个字段需额外3行冗余代码

最优解决方案

步骤1:定义通用的类型转换工具

利用Pydantic的Annotated和BeforeValidator实现通用的单值转列表逻辑,支持任意类型:

from typing import TypeVar, Any
from pydantic import BeforeValidator, Annotated

# 定义泛型变量,支持任意类型
T = TypeVar('T')

def single_to_list(v: Any) -> list[Any]:
    """将非列表值转为单元素列表,列表值保持不变"""
    if not isinstance(v, list):
        return [v]
    return v

# 封装为通用类型注解,底层类型为list[T]
SingleOrList = Annotated[list[T], BeforeValidator(single_to_list)]

步骤2:在Pydantic模型中声明字段

每个字段只需一行代码,直接使用SingleOrList[T]即可,类型检查会识别为list[T]:

from pydantic import BaseModel

class Config(BaseModel):
    fruit: SingleOrList[str]
    vegetable: SingleOrList[str]

# 推广至其他类型示例
class NumericConfig(BaseModel):
    count: SingleOrList[int]
    threshold: SingleOrList[float]

验证效果

解析示例YAML配置:

import yaml

yaml_content = """
fruit: apple
vegetable:
  - tomato
  - cucumber
"""

config_data = yaml.safe_load(yaml_content)
config = Config(**config_data)

print(config.fruit)       # 输出: ['apple']
print(config.vegetable)   # 输出: ['tomato', 'cucumber']
print(type(config.fruit)) # 输出: <class 'list'>

方案优势

  1. 类型安全:mypy会将SingleOrList[str]识别为list[str],无需额外类型断言
  2. 代码简洁:每个字段仅需一行声明,无重复验证逻辑
  3. 通用性强:替换str为任意类型(如int、bool甚至自定义类)即可适配不同场景

内容的提问来源于stack exchange,提问作者Koterpillar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 17:17:27