Como validar dados de uma API com Pydantic em Python
Quando consomes uma API REST em Python, nunca tens a garantia de que os dados chegam no formato esperado: um campo pode vir a null, um número pode chegar como texto e, de repente, o teu pipeline parte a meio do processamento. Validar dados de uma API com Pydantic resolve exatamente isto — defines um modelo com os tipos que esperas e o Pydantic verifica, converte e sinaliza tudo por ti, com mensagens de erro claras quando algo não bate certo. O resultado é código mais robusto e menos horas perdidas a caçar bugs causados por dados inesperados.
Pré-requisitos
- Python 3.9 ou superior instalado.
- Conhecimentos básicos de dicionários e da biblioteca
requests. - Pydantic v2 instalado com
pip install pydantic requests. - Uma API REST que devolva JSON (aqui usamos uma pública de exemplo).
Passo 1: Definir o modelo de dados
O primeiro passo para validar dados de uma API é descrever a forma que esperas receber. Num modelo Pydantic, cada campo tem um nome e um tipo; se os dados não corresponderem, a biblioteca levanta um erro em vez de deixar passar valores inválidos. Esta abordagem substitui o acesso frágil a dicionários (por exemplo, dados['id']), que falha em silêncio ou rebenta com um KeyError quando a estrutura muda.
from pydantic import BaseModel
class Utilizador(BaseModel):
id: int
name: str
email: str
ativo: bool = True
O campo ativo tem um valor por omissão (True), por isso é opcional: se a API não o enviar, o modelo assume esse valor automaticamente. Os restantes campos são obrigatórios. Definir tipos explícitos também serve de documentação viva: qualquer pessoa que leia o modelo percebe de imediato o que a API devolve.
Passo 2: Validar um único registo
Com o modelo pronto, valida um dicionário com o método model_validate(). Um detalhe útil: o Pydantic converte automaticamente tipos compatíveis, por isso a string "42" passa a ser o inteiro 42 sem esforço da tua parte. Se preferires impedir estas conversões automáticas e exigir tipos exatos, o Pydantic também suporta o modo estrito, mas para dados vindos de JSON a conversão flexível costuma ser o que queres.
dados = {"id": "42", "name": "Ana", "email": "ana@exemplo.pt"}
utilizador = Utilizador.model_validate(dados)
print(utilizador.id) # 42 (int, convertido de texto)
print(utilizador.ativo) # True (valor por omissão)
Passo 3: Apanhar erros de validação
Quando um campo obrigatório falta ou tem o tipo errado, o Pydantic lança a exceção ValidationError com uma descrição detalhada. Envolve a validação num try/except para tratares o problema sem interromper o programa.
from pydantic import ValidationError
mau = {"id": "abc", "name": "Rui"} # id não numérico e email em falta
try:
Utilizador.model_validate(mau)
except ValidationError as erro:
print(erro)
A mensagem indica exatamente qual o campo problemático e porquê. Isto torna a depuração muito mais rápida do que descobrir o erro três passos à frente, já dentro do pipeline.
Dica: valida os dados logo à entrada, assim que recebes a resposta da API. Quanto mais cedo apanhas um erro, mais barato é corrigi-lo.
Passo 4: Validar uma lista de registos
Na prática, uma API devolve quase sempre uma lista de objetos. Para validar todos de uma vez sem escrever um ciclo à mão, usa o TypeAdapter com o tipo list[Utilizador]. Assim, com uma linha, garantes que todos os registos respeitam o contrato definido no modelo.
import requests
from pydantic import TypeAdapter
resposta = requests.get("https://jsonplaceholder.typicode.com/users")
resposta.raise_for_status()
validador = TypeAdapter(list[Utilizador])
utilizadores = validador.validate_python(resposta.json())
print(f"{len(utilizadores)} utilizadores validados")
Os campos extra que a API envia e que não estão no modelo (como phone ou address) são simplesmente ignorados, ficando o teu objeto limpo e previsível.
Verificar o resultado
Faz duas verificações rápidas para confirmar que a validação funciona. Primeiro, com dados corretos, acede a um atributo e confirma o tipo — por exemplo, utilizadores[0].id deve devolver um inteiro. Segundo, força um erro de propósito: muda um id para texto não numérico e confirma que o ValidationError é lançado. Se ambos os comportamentos acontecerem, a tua camada de validação está pronta a proteger o pipeline.
Conclusão
Em quatro passos passaste a validar dados de uma API com Pydantic: definir o modelo, validar um registo, apanhar erros e validar listas inteiras. A partir daqui podes avançar para validações personalizadas com field_validator, campos opcionais mais ricos e a geração automática de JSON Schema a partir do modelo. Qual é o campo da tua API que mais precisa de uma regra de validação à medida?