类型适配器
您可能有并非 BaseModel
的类型,但您希望针对这些类型验证数据。或者您可能想要验证 list[SomeModel]
,或将其转储为 JSON。
对于这种情况,Pydantic 提供了 TypeAdapter
,它可以用于类型验证、序列化和 JSON 模式生成,而无需创建 BaseModel
。
TypeAdapter
实例为没有这些方法的类型(例如数据类、原始类型等)公开了来自 BaseModel
实例方法的部分功能
from typing_extensions import TypedDict
from pydantic import TypeAdapter, ValidationError
class User(TypedDict):
name: str
id: int
user_list_adapter = TypeAdapter(list[User])
user_list = user_list_adapter.validate_python([{'name': 'Fred', 'id': '3'}])
print(repr(user_list))
#> [{'name': 'Fred', 'id': 3}]
try:
user_list_adapter.validate_python(
[{'name': 'Fred', 'id': 'wrong', 'other': 'no'}]
)
except ValidationError as e:
print(e)
"""
1 validation error for list[User]
0.id
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='wrong', input_type=str]
"""
print(repr(user_list_adapter.dump_json(user_list)))
#> b'[{"name":"Fred","id":3}]'
from typing import TypedDict
from pydantic import TypeAdapter, ValidationError
class User(TypedDict):
name: str
id: int
user_list_adapter = TypeAdapter(list[User])
user_list = user_list_adapter.validate_python([{'name': 'Fred', 'id': '3'}])
print(repr(user_list))
#> [{'name': 'Fred', 'id': 3}]
try:
user_list_adapter.validate_python(
[{'name': 'Fred', 'id': 'wrong', 'other': 'no'}]
)
except ValidationError as e:
print(e)
"""
1 validation error for list[User]
0.id
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='wrong', input_type=str]
"""
print(repr(user_list_adapter.dump_json(user_list)))
#> b'[{"name":"Fred","id":3}]'
dump_json
返回 bytes
TypeAdapter
的 dump_json
方法返回一个 bytes
对象,这与 BaseModel
的对应方法 model_dump_json
返回 str
不同。造成这种差异的原因是,在 V1 版本中,模型转储返回的是 str 类型,因此在 V2 版本中保留了这种行为以实现向后兼容。对于 BaseModel
的情况,bytes
会被强制转换为 str
类型,但 bytes
通常是期望的最终类型。因此,对于 V2 版本中新的 TypeAdapter
类,返回类型直接为 bytes
,如果需要,可以很容易地将其强制转换为 str
类型。
注意
尽管 TypeAdapter
在用例上与 RootModel
有些重叠,但 TypeAdapter
不应被用作类型注解来指定 BaseModel
等的字段。
将数据解析为指定类型¶
TypeAdapter
可用于应用解析逻辑,以更 ad-hoc 的方式填充 Pydantic 模型。此函数的行为类似于 BaseModel.model_validate
,但适用于任意 Pydantic 兼容的类型。
当您想将结果解析为非 BaseModel
直接子类的类型时,这尤其有用。例如
from pydantic import BaseModel, TypeAdapter
class Item(BaseModel):
id: int
name: str
# `item_data` could come from an API call, eg., via something like:
# item_data = requests.get('https://my-api.com/items').json()
item_data = [{'id': 1, 'name': 'My Item'}]
items = TypeAdapter(list[Item]).validate_python(item_data)
print(items)
#> [Item(id=1, name='My Item')]
TypeAdapter
能够将数据解析为 Pydantic 可以作为 BaseModel
字段处理的任何类型。
性能考虑
当创建 TypeAdapter
实例时,必须分析提供的类型并将其转换为 pydantic-core 模式。这会带来一些不可忽略的开销,因此建议为给定类型仅创建一次 TypeAdapter
,并在循环或其他性能关键代码中重复使用它。
重建 TypeAdapter
的模式¶
在 v2.10+ 版本中,TypeAdapter
支持延迟模式构建和手动重建。这对于以下情况很有帮助:
- 带有前向引用的类型
- 核心模式构建成本很高的类型
当您使用类型初始化 TypeAdapter
时,Pydantic 会分析该类型并为其创建核心模式。此核心模式包含验证和序列化该类型数据所需的信息。有关核心模式的更多信息,请参阅架构文档。
如果在初始化 TypeAdapter
时将 defer_build
设置为 True
,Pydantic 将延迟构建核心模式,直到首次需要它时(用于验证或序列化)。
为了手动触发核心模式的构建,您可以调用 rebuild
方法 在 TypeAdapter
实例上
from pydantic import ConfigDict, TypeAdapter
ta = TypeAdapter('MyInt', config=ConfigDict(defer_build=True))
# some time later, the forward reference is defined
MyInt = int
ta.rebuild()
assert ta.validate_python(1) == 1