I use Pydantic to model the requests and responses to an API.
I defined a User
class:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
My API returns a list of users which I retrieve with requests
and convert into a dict:
users = [{"name": "user1", "age": 15}, {"name": "user2", "age": 28}]
How can I convert this dict to a list of User
instances?
My solution for now is
user_list = []
for user in users:
user_list.append(User(**user))
Pydantic models can be defined with a custom root type by declaring the __root__ field. The root type can be any type supported by pydantic, and is specified by the type hint on the __root__ field.
Pydantic models. Pydantic is a useful library for data parsing and validation. It coerces input types to the declared type (using type hints), accumulates all the errors using ValidationError & it's also well documented making it easily discoverable.
pydantic allows custom data types to be defined or you can extend validation with methods on a model decorated with the validator decorator. dataclasses integration. As well as BaseModel , pydantic provides a dataclass decorator which creates (almost) vanilla python dataclasses with input data parsing and validation.
This is now possible using 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)
To confirm and expand the previous answer, here is an "official" answer at pydantic-github - All credits to "dmontagu":
The "right" way to do this in pydantic is to make use of "Custom Root Types". You still need to make use of a container model:
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']},
])
(and will put the values inside the root property).
Unfortunately, I think there is not good serialization support for this yet, so I think when you go to return the results, if you want to return just a list you'll still need to return UserList.root.
I don't think there is currently a unified interface that gets you a serialized/unstructured version of the model that respects the root_model, but if this is what you are looking for, it could be worth building.
You can try this
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())
You could consider using a list comprehension along with dict unpacking to the User
constructor
user_list = [
User(**user) for user in users
]
You can use the __root__
Pydantic keyword:
from typing import List
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
class UserList(BaseModel):
__root__: List[User] # ⯇-- __root__
To build the JSON response:
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))
Your API web framework can jsonify user_list
to be returned as a JSON array (within the response body).
I just set in my models.py
list of dict like this:
from django.db import models
from pydantic import BaseModel
class CustomList(BaseModel):
data: list[dict]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With