13

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?

2
  • 1
    Notice you have "orm_mode = True" , most likely you are experiencing a problem with you ORM and not with your Pydantic models... can't say much more because you have not provided details or your ORM. Commented Apr 29, 2020 at 12:17
  • If you are POSTing json data, fastapi will try to convert it automatically to a pydantic model. Otherwise, you may simply declare a field as an array, as you did in Tests. Have you tried removing the "class Config: orm_mode = True" piece of code? Commented Apr 30, 2020 at 16:11

2 Answers 2

16

Update (26/09/2020)

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 Tests, 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.

Sign up to request clarification or add additional context in comments.

3 Comments

this is awesome! hadn't seen much good docs on how to return lists with FastAPI which seems like a super common use case.
This gives me a warning in PyCharm: Expected type 'Optional[type]', got 'GenericAlias' instead, but works.
@A.Rabus I get warning too. Should we use the typing List, or Python 3.9 list?
1

One thing that I was able to achieve with Pydantic V2 that plays nicely in OpenAPI is importing from RootModel instead of BaseModel:

class Test(BaseModel):
    name: str
    family: str
    class Config:
        orm_mode = True

class Tests(RootModel[List[Test]]):
    pass

but as highlighted above, this is not strictly necessary.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.