Recebendo Dados de Requisição como Objeto de Classe em FastAPI
O FastAPI permite mapear os dados de uma requisição diretamente para objetos de classes definidas pelo desenvolvedor. Essas classes devem herdar de pydantic.BaseModel e são projetadas para modelar os dados esperados na requisição.
Estrutura do Projeto
Para exemplificar, criaremos uma API que recebe um objeto contendo o nome e a idade de uma pessoa e retorna uma mensagem de boas-vindas com esses dados. A estrutura do projeto será organizada da seguinte forma:
. ├── public │ └── index.html ├── main.py
Interface Web
Para testar a API, criaremos uma interface web que simula um cliente enviando dados ao servidor. O arquivo index.html conterá:
<!DOCTYPE html>
<html>
  <head>
    <title>FastAPI Demo</title>
    <meta charset="utf-8" />
  </head>
  <body>
    <div id="message"></div>
    <p>
      Digite seu nome: <br />
      <input name="username" id="username" />
    </p>
    <p>
      Digite sua idade: <br />
      <input name="userage" id="userage" type="number" />
    </p>
    <button onclick="send()">Enviar</button>
    <script>
      async function send() {
        const username = document.getElementById("username").value;
        const userage = document.getElementById("userage").value;
        const response = await fetch("/hello", {
          method: "POST",
          headers: { Accept: "application/json", "Content-Type": "application/json" },
          body: JSON.stringify({
            name: username,
            age: userage,
          }),
        });
        if (response.ok) {
          const data = await response.json();
          document.getElementById("message").textContent = data.message;
        } else {
          console.log(response);
        }
      }
    </script>
  </body>
</html>Esse formulário captura os dados inseridos pelo usuário e os envia para o endpoint /hello via uma requisição POST.
Configurando p Backend
O arquivo main.py conterá a definição da API:
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel
class Person(BaseModel):
    name: str
    age: int
app = FastAPI()
@app.get("/")
def root():
    return FileResponse("public/index.html")
@app.post("/hello")
def hello(person: Person):
    return {"message": f"Olá, {person.name}, sua idade é {person.age}"}A classe Person é uma subclasse de BaseModel e define os campos name e age que serão mapeados a partir dos dados enviados pelo cliente.
O endpoint /hello recebe um objeto do tipo Person e retorna uma mensagem de boas-vindas contendo o nome e a idade da pessoa.

Atributos Opcionais
No FastAPI, é possível tornar alguns atributos opcionais, atribuindo-lhes None como valor padrão:
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel
class Person(BaseModel):
    name: str
    age: int | None = None
app = FastAPI()
@app.get("/")
def root():
    return FileResponse("public/index.html")
@app.post("/hello")
def hello(person: Person):
    if person.age is None:
        return {"message": f"Olá, {person.name}"}
    else:
        return {"message": f"Olá, {person.name}, sua idade é {person.age}"}Configuração Detalhada com Field
O módulo pydantic permite configurar validações e valores padrão com Field:
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel, Field
class Person(BaseModel):
    name: str = Field(default="Indefinido", min_length=3, max_length=20)
    age: int = Field(default=18, ge=18, lt=111)
app = FastAPI()
@app.get("/")
def root():
    return FileResponse("public/index.html")
@app.post("/hello")
def hello(person: Person):
    return {"message": f"Olá, {person.name}, sua idade é {person.age}"}Nesse exemplo, o campo name deve ter entre 3 e 20 caracteres e o campo age deve ser maior ou igual a 18 e menor que 111.
Trabalhando com Listas
É possível receber listas de objetos:
from fastapi import FastAPI
from pydantic import BaseModel
class Person(BaseModel):
    name: str
    age: int
app = FastAPI()
@app.post("/hello")
def hello(people: list[Person]):
    return {"message": people}Envio de exemplo com JavaScript:
const response = await fetch("/hello", {
  method: "POST",
  headers: { Accept: "application/json", "Content-Type": "application/json" },
  body: JSON.stringify([
    { name: "Tom", age: 38 },
    { name: "Bob", age: 41 },
    { name: "Sam", age: 25 },
  ]),
});
const data = await response.json();
console.log(data);Modelos Aninhados
Modelos podem conter outros modelos:
from fastapi import FastAPI
from pydantic import BaseModel
class Company(BaseModel):
    name: str
class Person(BaseModel):
    name: str
    company: Company
app = FastAPI()
@app.post("/hello")
def hello(person: Person):
    return {"message": f"{person.name} trabalha na empresa {person.company.name}"}Envio de exemplo com JavaScript:
const response = await fetch("/hello", {
  method: "POST",
  headers: { Accept: "application/json", "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "Tom",
    company: { name: "Google" },
  }),
});
const data = await response.json();
console.log(data);Documentação oficial: