What I want to achieve is to offer multiple examples to the users in the SwaggerUI with the dropdown menu.
The documentation has only an example with annotating a FastAPI object but not a pydantic class.
Here is an example how it works with examples
(CreateRequest1
) but CreateRequest2
with openapi_examples
does not work like I would expect:
from fastapi import FastAPI
from fastapi.openapi.models import Example
from pydantic import BaseModel, ConfigDict, Field
app = FastAPI()
class CreateRequest1(BaseModel):
name: str = Field(..., description="Name of the created item")
value: str = Field(..., description="Value of the created item")
model_config = ConfigDict(json_schema_extra={"examples": [{"name": "Item1", "value": "Value1"}]})
class CreateRequest2(BaseModel):
name: str = Field(..., description="Name of the created item")
value: str = Field(..., description="Value of the created item")
model_config = ConfigDict(
json_schema_extra={
"openapi_examples": {
"abc": Example(summary="test", description="test", value={"name": "Item1", "value": "Value1"})
}
}
)
@app.post("/1")
def create_item1(body: CreateRequest1):
return CreateRequest1.name
@app.post("/2")
def create_item2(body: CreateRequest2):
return CreateRequest2.name
According to documentation, This OpenAPI-specific examples goes in another section in the OpenAPI specification. It goes in the details for each path operation, not inside each JSON Schema.
.
So, these examples relate to the path operation, not to the input parameter’s schema.
You should pass these examples as a parameter of Path()
, Query()
, Header()
, Cookie()
, Body()
, etc..
It’s shown in the documentation how to use openapi_examples
:
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Annotated[
Item,
Body(
openapi_examples={
"normal": {
"summary": "A normal example",
"description": "A **normal** item works correctly.",
"value": {
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
},
"converted": {
"summary": "An example with converted data",
"description": "FastAPI can convert price `strings` to actual `numbers` automatically",
"value": {
"name": "Bar",
"price": "35.4",
},
},
"invalid": {
"summary": "Invalid data is rejected with an error",
"value": {
"name": "Baz",
"price": "thirty five point four",
},
},
},
),
],
):
results = {"item_id": item_id, "item": item}
return results
I think it’s possible to store these examples in private field of pydantic model (class attribute) and pass it to Body() like:
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Annotated[
Item,
Body(
openapi_examples=Item._openapi_examples,
),
],
):
results = {"item_id": item_id, "item": item}
return results