Search code examples
pythonrestswaggerfastapivariant

How do I accept on a single route objects with array\single items using pydantic/fastapi?


Say I have:

from pydantic import BaseModel
from typing import Optional, List

class Create(BaseModel):
    code: List[str] = []
    args: List[str] = []

Wrapped into something like

@router.post('/new', status_code=201)
async def create_project(data: Create):
    pass

So that code and/or args is an array or single value for the requestor?

Such that request to single rout could contain any of this:

{code: "code", args: "arg"}
{code: ["code"], args: "arg"}
{code: ["code"], args: ["arg"]}
{code: "code", args: ["arg"]}

And always call handler with real type that uses lists?


Solution

  • Pydantic models accept Union for the field definition, e.g.:

    from typing import List, Union
    
    class Create(BaseModel):
        code: Union[str, List[str]] = []
        args: Union[str, List[str]] = []
    

    In this case, both code and args will accept either a str or a list/array of strs.

    Both code and args will default to an empty list.

    The rest of the code stays the same, e.g.:

    from fastapi import FastAPI, status
    
    app = FastAPI()
    
    @app.post("/create", status_code=status.HTTP_201_CREATED)
    async def create_project(data: Create):
        return data
    

    Calling the endpoint with single item:

    $ curl -i -X 'POST' 'http://127.0.0.1:8000/create' \
        -H 'accept: application/json' \
        -H 'Content-Type: application/json' \
        -d '{"code": "code", "args": "arg"}'
    
    HTTP/1.1 201 Created
    date: Sun, 29 Aug 2021 10:25:57 GMT
    server: uvicorn
    content-length: 28
    content-type: application/json
    
    {"code":"code","args":"arg"}
    

    Calling the endpoint with multiple items:

    $ curl -i -X 'POST' 'http://127.0.0.1:8000/create' \
        -H 'accept: application/json' \
        -H 'Content-Type: application/json' \
        -d '{"code": ["code"], "args": ["arg"]}'
    
    HTTP/1.1 201 Created
    date: Sun, 29 Aug 2021 10:27:03 GMT
    server: uvicorn
    content-length: 32
    content-type: application/json
    
    {"code":["code"],"args":["arg"]}