I am writing an app where I need to have two completely different set of response structures depending on logic.
Is there any way to handle this so that I can have two different response models serialized, validated and returned and reflect in OpenAPI JSON?
I am using pydantic to write models.
Yes this is possible. You can use Union for that in the response_model= parameter in your path decorator (I used the new python 3.10 style below). Here is a full example, this will work as is.
from typing import Union
from fastapi import FastAPI, Query
from pydantic import BaseModel
class responseA(BaseModel):
name: str
class responseB(BaseModel):
id: int
app = FastAPI()
@app.get("/", response_model=Union[responseA,responseB])
def base(q: int|str = Query(None)):
if q and isinstance(q, str):
return responseA(name=q)
if q and isinstance(q, int):
return responseB(id=q)
raise HTTPException(status_code=400, detail="No q param provided")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000, )
EDIT: As pointed out by TomášLinhart in the comments below, the response_model parameter must use Union. In the original answer, I used the 3.10 style responseA|responseB which did not work for everybody as explained here in the docs.
Result in your documentation:

If you need response multiple examples, you can try this:
@router.get(
'/{UserId}',
summary='get user',
responses={
200: {
"description": "",
"content": {
"application/json": {
"examples": {
"Corporate user": {
'value': {
'foo': 'bar',
},
},
"Standard user": {
'value': {
'doo': 'www',
},
},
}
}
}
}
}
)

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