如何使用Pydantic解析模型列表

时间:2019-04-19 13:31:22

标签: python pydantic

我使用Pydantic对API的请求和响应进行建模。

我定义了一个User类:

from pydantic import BaseModel

class User(BaseModel):
  name: str
  age: int

我的API返回一个用户列表,我用requests检索并转换成字典:

users = [{"name": "user1", "age": 15}, {"name": "user2", "age": 28}]

如何将此字典转换为User个实例的列表?

我目前的解决方案是

user_list = []
for user in users:
  user_list.append(User(**user))

6 个答案:

答案 0 :(得分:19)

现在可以使用parse_obj_as

from pydantic import parse_obj_as

users = [
    {"name": "user1", "age": 15}, 
    {"name": "user2", "age": 28}
]

m = parse_obj_as(List[User], users)

答案 1 :(得分:3)

要确认并扩展先前的answer,请在pydantic-github处给出“正式”答案-所有功劳归于“ dmontagu ”:

  

在pydantic中执行此操作的“正确”方法是利用“自定义根”   类型”。您仍然需要使用容器模型:

class UserList(BaseModel):
    __root__: List[User]
but then the following will work:

UserList.parse_obj([
    {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']},
    {'id': '456', 'signup_ts': '2017-06-02 12:22', 'friends': ['you']},
])
  

(并将这些值放在 root 属性中)。

     

不幸的是,我认为没有很好的序列化支持   这还没有,所以我想如果您想返回结果   仅返回一个列表,您仍然需要返回UserList。 root

     

我认为目前没有统一的界面可以让您   该模型的序列化/非结构化版本    root_model ,但是如果您正在寻找它,那么可能值得构建。

答案 2 :(得分:0)

您可以尝试

from typing import List
from pydantic import BaseModel

class User(BaseModel):
  name: str
  age: int

class Users(BaseModel):
    users: List[User]

users = [{"name": "user1", "age": 15}, {"name": "user2", "age": 28}]
m = Users(users=users)
print(m.dict())

答案 3 :(得分:0)

您可以考虑使用列表理解以及将dict解压缩到User构造函数中

user_list = [
  User(**user) for user in users
]

答案 4 :(得分:0)

您可以使用__root__ Pydantic关键字:

from typing import List
from pydantic import BaseModel

class User(BaseModel):
  name: str
  age: int

class UserList(BaseModel):
  __root__: List[User]     # ⯇-- __root__

要构建JSON响应:

user1 = {"name": "user1", "age": 15}
user2 = {"name": "user2", "age": 28}

user_list = UserList(__root__=[])
user_list.__root__.append(User(**user1))
user_list.__root__.append(User(**user2))

您的API网络框架可以对user_list进行JSON加密,以JSON数组的形式返回(在响应体内)。

答案 5 :(得分:0)

如果低于 1.2 的 pydantic 版本不支持 parse_obj_as 方法,我还有另一个想法来简化此代码。

user_list = []
for user in users:
  user_list.append(User(**user))

简单的方法

user_list = [User(**user) for user in users]