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?
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.