How to use openapi_examples from a pydantic model in FastAPI?

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

Leave a Comment