Skip to content

Schema Extra - Example

You can define extra information to go in JSON Schema.

A common use case is to add an example that will be shown in the docs.

There are several ways you can declare extra JSON Schema information.

Pydantic schema_extra

You can declare an example for a Pydantic model using Config and schema_extra, as described in Pydantic's docs: Schema customization:

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None

    class Config:
        schema_extra = {
            "example": {
                "name": "Foo",
                "description": "A very nice Item",
                "price": 35.4,
                "tax": 3.2,
            }
        }


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

That extra info will be added as-is to the output JSON Schema.

Field additional arguments

In Field, Path, Query, Body and others you'll see later, you can also declare extra info for the JSON Schema by passing any other arbitrary arguments to the function, for example, to add an example:

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()


class Item(BaseModel):
    name: str = Field(..., example="Foo")
    description: Optional[str] = Field(None, example="A very nice Item")
    price: float = Field(..., example=35.4)
    tax: Optional[float] = Field(None, example=3.2)


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

Warning

Have in mind that those extra arguments passed won't add any validation, only annotation, for documentation purposes.

Body additional arguments

The same way you can pass extra info to Field, you can do the same with Path, Query, Body, etc.

For example, you can pass an example for a body request to Body:

from typing import Optional

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


@app.put("/items/{item_id}")
async def update_item(
    item_id: int,
    item: Item = Body(
        ...,
        example={
            "name": "Foo",
            "description": "A very nice Item",
            "price": 35.4,
            "tax": 3.2,
        },
    ),
):
    results = {"item_id": item_id, "item": item}
    return results

Example in the docs UI

With any of the methods above it would look like this in the /docs:

Body with multiple examples

For simple routes which accept only a single Body request, the Body constuctor will also accept an examples keyword (plural) to which you can attach a series of examples.

This can be useful when you need to communicate with the users of your API about how the FastAPI application will handle specific user input situations, and what they can expect to receive in return in your responses.

As a simple example, if you wish to show users that the API will elegantly handle numbers passed as strings or as numbers you might pass a few examples to Body like so:

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int,
    item: Item = Body(
        ...,
        examples={
            "case1": {
                "summary": "valid test case",
                "value": {
                    "name": "Foo",
                    "description": "A very nice Item",
                    "price": 35.4,
                    "tax": 3.2,
                },
            },
            "case2": {
                "summary": "valid test case with type coersion",
                "value": {
                    "name": "Bar",
                    "description": "Another very nice Item",
                    "price": "35.4",
                    "tax": 3.2,
                },
            },
            "case3": {
                "summary": "invalid test case with wrong type",
                "value": {
                    "name": "Baz",
                    "description": "One more very nice Item",
                    "price": "thirty five point four",
                    "tax": 3.2,
                },
            },
        },
    ),
):
    results = {"item_id": item_id, "item": item}
    return results

With examples added to Body it would look like this in the /docs:

Technical Details

About example vs examples...

JSON Schema defines a field examples in the most recent versions, but OpenAPI is based on an older version of JSON Schema that didn't have examples.

So, OpenAPI defined its own example for the same purpose (as example, not examples), and that's what is used by the docs UI (using Swagger UI).

So, although example is not part of JSON Schema, it is part of OpenAPI, and that's what will be used by the docs UI.

Other info

The same way, you could add your own custom extra info that would be added to the JSON Schema for each model, for example to customize a frontend user interface, etc.