Declare um exemplo dos dados da requisição¶
Você pode declarar exemplos dos dados que a sua aplicação pode receber.
Aqui estão várias formas de se fazer isso.
schema_extra
do Pydantic¶
Você pode declarar um example
para um modelo Pydantic usando Config
e schema_extra
, conforme descrito em Documentação do Pydantic: Schema customization:
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
model_config = {
"json_schema_extra": {
"examples": [
{
"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
🤓 Other versions and variants
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
model_config = {
"json_schema_extra": {
"examples": [
{
"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
Essas informações extras serão adicionadas como se encontram no JSON Schema de resposta desse modelo e serão usadas na documentação da API.
Dica
Você pode usar a mesma técnica para estender o JSON Schema e adicionar suas próprias informações extras de forma personalizada.
Por exemplo, você pode usar isso para adicionar metadados para uma interface de usuário de front-end, etc.
Field
de argumentos adicionais¶
Ao usar Field ()
com modelos Pydantic, você também pode declarar informações extras para o JSON Schema passando quaisquer outros argumentos arbitrários para a função.
Você pode usar isso para adicionar um example
para cada campo:
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str = Field(examples=["Foo"])
description: Union[str, None] = Field(default=None, examples=["A very nice Item"])
price: float = Field(examples=[35.4])
tax: Union[float, None] = Field(default=None, examples=[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
🤓 Other versions and variants
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str = Field(examples=["Foo"])
description: str | None = Field(default=None, examples=["A very nice Item"])
price: float = Field(examples=[35.4])
tax: float | None = Field(default=None, examples=[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
Atenção
Lembre-se de que esses argumentos extras passados não adicionarão nenhuma validação, apenas informações extras, para fins de documentação.
example
e examples
no OpenAPI¶
Ao usar quaisquer dos:
Path()
Query()
Header()
Cookie()
Body()
Form()
File()
você também pode declarar um dado example
ou um grupo de examples
com informações adicionais que serão adicionadas ao OpenAPI.
Body
com example
¶
Aqui nós passamos um example
dos dados esperados por Body()
:
from typing import Union
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Item = Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
}
],
),
):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Annotated
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Annotated[
Item,
Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
}
],
),
],
):
results = {"item_id": item_id, "item": item}
return results
from typing import Annotated, Union
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Annotated[
Item,
Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
}
],
),
],
):
results = {"item_id": item_id, "item": item}
return results
from typing import Union
from fastapi import Body, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Annotated[
Item,
Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
}
],
),
],
):
results = {"item_id": item_id, "item": item}
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(
item_id: int,
item: Item = Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
}
],
),
):
results = {"item_id": item_id, "item": item}
return results
Exemplo na UI da documentação¶
Com qualquer um dos métodos acima, os /docs
vão ficar assim:
Body
com vários examples
¶
Alternativamente ao único example
, você pode passar examples
usando um dict
com vários examples, cada um com informações extras que serão adicionadas no OpenAPI também.
As chaves do dict
identificam cada exemplo, e cada valor é outro dict
.
Cada dict
de exemplo específico em examples
pode conter:
summary
: Pequena descrição do exemplo.description
: Uma descrição longa que pode conter texto em Markdown.value
: O próprio exemplo mostrado, ex: umdict
.externalValue
: alternativa aovalue
, uma URL apontando para o exemplo. Embora isso possa não ser suportado por tantas ferramentas quantovalue
.
from typing import Union
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Item = Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
{
"name": "Bar",
"price": "35.4",
},
{
"name": "Baz",
"price": "thirty five point four",
},
],
),
):
results = {"item_id": item_id, "item": item}
return results
🤓 Other versions and variants
from typing import Annotated
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Annotated[
Item,
Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
{
"name": "Bar",
"price": "35.4",
},
{
"name": "Baz",
"price": "thirty five point four",
},
],
),
],
):
results = {"item_id": item_id, "item": item}
return results
from typing import Annotated, Union
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Annotated[
Item,
Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
{
"name": "Bar",
"price": "35.4",
},
{
"name": "Baz",
"price": "thirty five point four",
},
],
),
],
):
results = {"item_id": item_id, "item": item}
return results
from typing import Union
from fastapi import Body, FastAPI
from pydantic import BaseModel
from typing_extensions import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Annotated[
Item,
Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
{
"name": "Bar",
"price": "35.4",
},
{
"name": "Baz",
"price": "thirty five point four",
},
],
),
],
):
results = {"item_id": item_id, "item": item}
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Item = Body(
examples=[
{
"name": "Foo",
"description": "A very nice Item",
"price": 35.4,
"tax": 3.2,
},
{
"name": "Bar",
"price": "35.4",
},
{
"name": "Baz",
"price": "thirty five point four",
},
],
),
):
results = {"item_id": item_id, "item": item}
return results
Exemplos na UI da documentação¶
Com examples
adicionado a Body()
, os /docs
vão ficar assim:
Detalhes técnicos¶
Atenção
Esses são detalhes muito técnicos sobre os padrões JSON Schema e OpenAPI.
Se as ideias explicadas acima já funcionam para você, isso pode ser o suficiente, e você provavelmente não precisa desses detalhes, fique à vontade para pular.
Quando você adiciona um exemplo dentro de um modelo Pydantic, usando schema_extra
ouField(example="something")
esse exemplo é adicionado ao JSON Schema para esse modelo Pydantic.
E esse JSON Schema do modelo Pydantic está incluído no OpenAPI da sua API e, em seguida, é usado na UI da documentação.
O JSON Schema na verdade não tem um campo example
nos padrões. Versões recentes do JSON Schema definem um campo examples
, mas o OpenAPI 3.0.3 é baseado numa versão mais antiga do JSON Schema que não tinha examples
.
Por isso, o OpenAPI 3.0.3 definiu o seu próprio example
para a versão modificada do JSON Schema que é usada, para o mesmo próposito (mas é apenas example
no singular, não examples
), e é isso que é usado pela UI da documentação da API(usando o Swagger UI).
Portanto, embora example
não seja parte do JSON Schema, é parte da versão customizada do JSON Schema usada pelo OpenAPI, e é isso que vai ser usado dentro da UI de documentação.
Mas quando você usa example
ou examples
com qualquer um dos outros utilitários (Query()
, Body()
, etc.) esses exemplos não são adicionados ao JSON Schema que descreve esses dados (nem mesmo para versão própria do OpenAPI do JSON Schema), eles são adicionados diretamente à declaração da operação de rota no OpenAPI (fora das partes do OpenAPI que usam o JSON Schema).
Para Path()
, Query()
, Header()
, e Cookie()
, o example
e examples
são adicionados a definição do OpenAPI, dentro do Parameter Object
(na especificação).
E para Body()
, File()
, e Form()
, o example
e examples
são de maneira equivalente adicionados para a definição do OpenAPI, dentro do Request Body Object
, no campo content
, no Media Type Object
(na especificação).
Por outro lado, há uma versão mais recente do OpenAPI: 3.1.0, lançada recentemente. Baseado no JSON Schema mais recente e a maioria das modificações da versão customizada do OpenAPI do JSON Schema são removidas, em troca dos recursos das versões recentes do JSON Schema, portanto, todas essas pequenas diferenças são reduzidas. No entanto, a UI do Swagger atualmente não oferece suporte a OpenAPI 3.1.0, então, por enquanto, é melhor continuar usando as opções acima.