I am using FastAPI to write a web service. It is good and fast.
FastAPI is using pydantic models to validate input and output data, everything is good but when I want to declare a nested model for array of jsons like below:
[
{
"name": "name1",
"family": "family1"
},
{
"name": "name2",
"family": "family2"
}
]
I get empty response.
I think there is a problem with my model which is:
class Test(BaseModel):
name: str
family: str
class Config:
orm_mode = True
class Tests(BaseModel):
List[Test]
class Config:
orm_mode = True
So, my question is how should I write a model for array of jsons?
Pydantic models are structures that ingest the data, parse it and make sure it conforms to the fields' constraints defined in it. Let's start with a simple example, where we define a Person class that has two fields without any constraints: first_name and last_name . Just like dataclasses, we use type annotations.
Defining an object in pydantic is as simple as creating a new class which inherits from the BaseModel . When you create a new object from the class, pydantic guarantees that the fields of the resultant model instance will conform to the field types defined on the model.
constr is a specific type that give validation rules regarding this specific type. You have equivalent for all classic python types.
In Python 3.9 (not yet released), you can do the same as below but with the built-in list
generic type (which is always in scope) rather than needing to import the capitalized List
type from typing
, e.g.
@app.get("/tests", response_model=list[Test])
The issue here is that you are trying to create a pydantic model where it is not needed. If you want to serialize/deserialize a list of objects, just wrap your singular model in a List[]
from python's builtin typing
module. There is no need to try to create a plural version of your object with a pydantic BaseModel
(and as you can see, it does not work anyway).
With that said, the simplest way to do what you want is to just specify a List[Test]
at any point where you need a list of Test
s, e.g.
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
existing_tests = [
{
"name": "name1",
"family": "family1"
},
{
"name": "name2",
"family": "family2"
}
]
class Test(BaseModel):
name: str
family: str
class Config:
orm_mode = True
app = FastAPI()
@app.get("/tests", response_model=List[Test])
async def fetch_tests():
return existing_tests
@app.post("/tests")
async def submit_tests(new_tests: List[Test]):
print(new_tests)
But of course if you find yourself repeatedly (or only) specifying Test
as a list, you can of course just assign this to a variable and then use that variable where needed, like so:
Tests = List[Test]
@app.get("/tests", response_model=Tests)
async def fetch_tests():
return existing_tests
@app.post("/tests")
async def submit_tests(new_tests: Tests):
print(new_tests)
I think the first option is probably slightly clearer in your code though, and unless you are specifying List[Test]
many times, using a variable for this purpose is probably not worth the extra layer of indirection.
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