Skip to content

Instantly share code, notes, and snippets.

@vigneshjs
Last active October 8, 2024 04:37
Show Gist options
  • Save vigneshjs/f17b3a2ec9ab9a606f37572bfdd1d76c to your computer and use it in GitHub Desktop.
Save vigneshjs/f17b3a2ec9ab9a606f37572bfdd1d76c to your computer and use it in GitHub Desktop.
Adding multiple request body examples to swagger docs in fastAPI
"""
FastAPI uses pydantic models to validate the API request body and also generate the swagger documentation. Since the schema
generated by pydantic only comply to JSON schema specification and not to openAPI specification, swagger documentation
generated from pydantic models do not support adding multiple examples for a request body.
Ref: https://fastapi.tiangolo.com/tutorial/schema-extra-example/#technical-details
In the following code, I have extended fastAPI openAPI schema to include multiple request body examples.
"""
import json
from fastapi import FastAPI, routing, status
from fastapi.openapi.utils import get_openapi
from fastapi.responses import Response
from pydantic import BaseModel
app = FastAPI()
# Defining a basic pydantic class that will be used by fastAPI to validate request body and generate swagger
class Sample(BaseModel):
"""
This is a example pydantic model
"""
name: str
email: str
mobile_number: str
password: str
otp: str
class Config:
# Follow openAPI 3.0 specification for defining examples. Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#example-object
schema_extra = {
"examples": {
"Login with otp": {
"description": "Allows to user to login with mobile_number and OTP",
"value": {
"mobile_number": "+9157878787878",
"opt": "123321"
}
},
"Login with email": {
"description": "Allows to user to login with email and password",
"value": {
"email": "[email protected]",
"password": "userPassword"
}
}
}
}
@app.post("/login", status_code=200)
async def login(body: Sample):
"""
Login user
"""
return Response({
"status": "success"
}, status_code=status.HTTP_200_OK)
# Extending openapi
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Sample API",
version="0.1.0",
description="These APIs will be used to manage developer portal and configure applications and permissions",
routes=app.routes,
)
# Adding examples present in pydancticModel.schema_extra into openAPI schema
for route in app.routes:
if isinstance(route, routing.APIRoute):
# bodyField refers to the field present in the function that is called when route matches
bodyField = route.body_field
if bodyField:
# Use pydantic schema_json() to get json schema representation (string) of the pydantic model
modelSchema = bodyField.type_.schema_json()
if modelSchema:
# Parse dict object from json string
jsonModelSchema = json.loads(modelSchema)
if "examples" in jsonModelSchema:
examples = jsonModelSchema['examples']
for method in route.methods:
# We can have requestBody examples only for POST and PUT methods
if method == "POST":
openapi_schema['paths'][route.path]["post"]['requestBody'][
'content']['application/json']['examples'] = examples
elif method == "PUT":
openapi_schema['paths'][route.path]["put"]['requestBody'][
'content']['application/json']['examples'] = examples
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment