是否可以使用pydantic自动将Union类型转换为仅一种类型



给定以下数据模型:


class Demo(BaseModel):
id: Union[int, str]
files: Union[str, List[str]]

有没有办法告诉pydantic,当我访问它们时,总是自动将id转换为str类型,将files转换为List[str]类型,而不是每次都手动转换。

Pydantic为大多数常见类型内置了验证逻辑。这包括str。默认情况下,默认字符串验证器只是将类型为intfloatDecimal的值强制为str。(参见str_validator来源)

这意味着,即使将id注释为str,但传递了int值,模型也将正确初始化而不会出现验证错误,并且id值将是该值的str版本。(例如str(42)给出"42")

list还内置了一个默认的验证器,但在这种情况下,它可能不是您想要的。如果它遇到一个非list值,但看到它是一个序列(或生成器),它会再次将其强制为list。(请参阅list_validator来源)在这种情况下,由于您可能传递给它的值将是str,而str是一个序列,因此结果将是初始字符串中的单个字符串列表。(例如list("abc")给出["a", "b", "c"])

因此,对于list[str],您可能需要自己的自定义pre=True验证器来使用str值执行您认为必要的任何操作,以将其转换为list[str]

示例:

from pydantic import BaseModel, validator

class Demo(BaseModel):
id: str
files: list[str]
@validator("files", pre=True)
def str_to_list_of_str(cls, v: object) -> object:
if isinstance(v, str):
return v.split(",")
return v

if __name__ == "__main__":
obj = Demo.parse_obj({"id": 42, "files": "foo,bar,baz"})
print(obj)
print(type(obj.id), type(obj.files))

输出:

id='42' files=['foo', 'bar', 'baz']
<class 'str'> <class 'list'>

正如您所看到的,如果您的值是int,您甚至不需要任何额外的id字段逻辑,因为它们在模型实例上最终为str

在得到维护人员的帮助后,我想出了如何制作它。关键是从类型定义中删除Union,并在验证前使用预处理钩子转换值,以下是示例代码:

from pydantic import BaseModel, validator
from typing import List
class Demo(BaseModel):
id: str
files: List[str]
@validator('id', pre=True)
def id_must_be_str(cls, v):
if isinstance(v, int):
v = str(v)
return v
@validator('files', pre=True)
def files_must_be_list_of_str(cls, v):
if isinstance(v, str):
v = [v]
return v

obj = Demo.parse_obj({'id': 1, 'files': '/data/1.txt'})
print(type(obj.id))
print(type(obj.files))

相关内容