pydantic v2 下,如何实现对象化一个列表?

作者站长头像
站长
· 阅读数 14

pydantic v2 下,如何实现对象化一个列表?作为 ptdantic v1 下 parse_obj_as 的替代品

需求:

一般都是把 dict 转成 pydantic 对象,但是如果我有很多个 dict,我需要转成一堆 pydantic 对象,比如把 list[dict] 转成 list[Item], 我会用列表生成式 [Item.model_validate(d) for d in dict_list]

但是有除了列表生成式之外更加优雅的方式吗?而且我主要担心的是,列表生成式不是最佳性能方案?

因为有一个程序需要频繁且巨量的序列化和反序列化,我需要关注性能


下面是 chatgpt 给我的答案:

如果你希望避免创建额外的 Pydantic 模型,同时直接对象化一个列表,可以利用 Pydantic 的 parse_obj_as 函数。这个函数允许你将一个普通的列表解析为 Pydantic 对象的列表。

下面是一个简洁的例子,展示如何直接对象化一个列表,而不需要创建额外的容器模型:

  1. 定义 Pydantic 模型

    • 仅定义一个表示列表项的模型。
from pydantic import BaseModel, parse_obj_as
from typing import List

class Item(BaseModel):
    id: int
    name: str

# 示例数据
data = [
    {"id": 1, "name": "Item 1"},
    {"id": 2, "name": "Item 2"}
]

# 解析数据
items = parse_obj_as(List[Item], data)

# 打印结果
for item in items:
    print(item)

在这个例子中:

  • Item 模型表示列表中的单个项。
  • data 是一个字典列表,表示需要解析的数据。
  • parse_obj_as(List[Item], data)data 解析为 Item 对象的列表。
  1. 访问列表中的数据

    • 解析后的 itemsItem 对象的列表,可以直接操作。
for item in items:
    print(f"ID: {item.id}, Name: {item.name}")

这种方法避免了创建额外的容器模型,保持了代码的简洁性,同时利用 Pydantic 的数据验证和类型检查功能。

上面的回答在 pydantic v1 下面确实是可以使用的,但是 pydantic v2 的 api 变更了

pydantic v2 下,如何实现对象化一个列表?

@deprecated(
    '`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.',
    category=None,
)
def parse_obj_as(type_: type[T], obj: Any, type_name: NameFactory | None = None) -> T:
    warnings.warn(
        '`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.',
        category=PydanticDeprecatedSince20,
        stacklevel=2,
    )
    if type_name is not None:  # pragma: no cover
        warnings.warn(
            'The type_name parameter is deprecated. parse_obj_as no longer creates temporary models',
            DeprecationWarning,
            stacklevel=2,
        )
    return TypeAdapter(type_).validate_python(obj)

因为 chatgpt 的数据库比较老,只有 pydantic v1 的,而我需要 v2 的

但是关于上面的代码提示我不知道去哪里导入 validate_python?

pydantic v2 下,如何实现对象化一个列表?

回复
1个回答
avatar
test
2024-06-19

TypeAdapter:https://docs.pydantic.dev/2.1/usage/type_adapter/

from typing import List

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')]
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容