Todos os artigos
142 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Tutoriais

Schema validation para JSON: validando o formato, não só a sintaxe

JSON válido não é JSON correto. Veja como usar JSON Schema para validar o formato esperado na borda da API, no config e nos contratos entre serviços.

Schema validation para JSON: validando o formato, não só a sintaxe
COVER · Tutoriais

A API aceitou o payload, respondeu 200, e três serviços lá na frente quebraram. O motivo: o front mandou "42" (string) onde o contrato dizia 42 (number), e ninguém checou. O JSON era sintaticamente perfeito — chaves fechadas, vírgulas no lugar, aspas corretas — e mesmo assim estava errado. Essa é a distância entre "isto é JSON válido" e "isto é o JSON que eu esperava", e é exatamente o buraco que schema validation existe para tapar.

Este guia mostra a diferença entre validar sintaxe e validar formato, o que é JSON Schema, onde aplicar a validação e por que um schema compartilhado vale mais que dez if defensivos espalhados pelo código.

Sintaxe válida não é o mesmo que formato correto

Validar sintaxe responde a uma pergunta: "isto é JSON parseável?". Qualquer JSON.parse faz isso e estoura se você esqueceu uma vírgula. Mas ele aceita feliz um objeto com o campo errado, um número onde devia ter texto, ou um email faltando — porque sintaticamente está tudo certo.

Schema validation responde a uma pergunta diferente e mais útil: "este JSON tem a forma que o meu sistema espera?". Os campos certos existem? Os tipos batem? O status é um dos valores permitidos? É a checagem que separa um dado que só parece certo de um que realmente é.

O que é JSON Schema

JSON Schema é um padrão (ele próprio escrito em JSON) para declarar a forma esperada de um documento. Você descreve tipos, campos obrigatórios, valores permitidos, formatos e limites, e valida qualquer payload contra essa descrição.

{
  "type": "object",
  "required": ["id", "email", "status"],
  "properties": {
    "id":     { "type": "integer", "minimum": 1 },
    "email":  { "type": "string", "format": "email" },
    "status": { "type": "string", "enum": ["active", "inactive"] },
    "tags":   { "type": "array", "items": { "type": "string" } }
  },
  "additionalProperties": false
}

Esse schema rejeita o payload do começo do artigo na hora:

{ "id": "42", "email": "joao@", "status": "ligado" }

Três erros de uma vez: id é string e não integer, email não tem formato válido, e status não está no enum. E o melhor: o validador aponta onde cada um falhou, em vez de um genérico "dados inválidos".

Valide na borda, sempre

A regra é simples: todo dado que vem de fora é não-confiável até ser validado, e a validação acontece na borda — no ponto de entrada, antes de qualquer lógica de negócio. Isso vale para:

  • Entrada de API — valide o body da request contra o schema antes de processar. Falhe com 400 e um erro claro, não com um stack trace três camadas abaixo.
  • Arquivos de configuração — um schema para o seu config.json pega o typo no nome da chave no startup, não em produção às duas da manhã.
  • Contratos entre serviços — o serviço A produz, o serviço B consome, e os dois validam contra o mesmo schema. Ninguém precisa adivinhar o formato do outro.

Para checar um payload contra o schema sem subir nada, o validador de JSON Schema faz isso direto no navegador e mostra o caminho exato de cada erro — útil quando o que você quer é só confirmar um contrato antes de codar contra ele.

Tooling: você não escreve o validador

Ninguém implementa validação de schema na mão. Cada linguagem tem uma biblioteca madura: Ajv em JavaScript/TypeScript (rápida, compila o schema), jsonschema em Python, e equivalentes em praticamente todo ecossistema. Elas implementam a especificação, então o mesmo schema funciona em qualquer lado do contrato.

import Ajv from "ajv";
import addFormats from "ajv-formats";

const ajv = addFormats(new Ajv({ allErrors: true }));
const validate = ajv.compile(schema);

if (!validate(payload)) {
  // cada erro traz instancePath + message — devolva isso, não um 500
  console.log(validate.errors);
}

Note o allErrors: true: por padrão muitos validadores param no primeiro erro. Ligar isso devolve a lista completa de uma vez, o que é muito melhor para quem está do outro lado tentando arrumar o request.

Gerar o schema a partir de um exemplo

Escrever o primeiro schema na mão é chato. Um atalho honesto: pegue um payload de exemplo real e gere o schema inicial a partir dele com uma ferramenta de inferência, depois ajuste — aperte os enum, marque os required, troque um string genérico por format: "email". É muito mais rápido que partir do zero, e te força a olhar campo por campo, que é justamente o ponto. Se você ainda está no degrau anterior — garantindo que o JSON sequer parseia —, vale ver primeiro como validar JSON e os erros de sintaxe mais comuns.

Perguntas frequentes

Qual a diferença entre validar JSON e validar com schema?

Validar JSON checa a sintaxe: se o texto é parseável (vírgulas, aspas, chaves). Validar com schema checa a forma: se os campos, tipos e valores batem com o esperado. Um JSON pode passar na primeira e falhar na segunda — é o caso clássico do número que veio como string. Você quer as duas, nessa ordem.

Onde devo colocar a validação de schema?

Na borda do sistema, antes da lógica de negócio: entrada de API, leitura de config, e em ambos os lados de um contrato entre serviços. A ideia é falhar rápido e com erro claro (caminho + motivo), em vez de deixar um dado torto vazar para dentro e quebrar três camadas depois.

Preciso escrever o validador eu mesmo?

Não, e não deveria. Use bibliotecas que implementam a especificação — Ajv em JS, jsonschema em Python e equivalentes. Elas cobrem os casos extremos da spec que você não quer reimplementar, e o mesmo schema roda igual em todas, o que é o ponto de ter um padrão.

JSON Schema substitui a validação de regra de negócio?

Não. Schema valida estrutura (tipos, obrigatoriedade, formato, faixas) — "este campo é um e-mail bem formado?". Regra de negócio é outra coisa — "este e-mail já está cadastrado?" exige consultar o banco. Use schema para a forma e mantenha as regras de domínio em código separado.

O que levar deste guia

JSON válido não é JSON correto. A sintaxe garante que o texto parseia; o schema garante que ele tem a forma que o seu sistema espera. Declare essa forma uma vez com JSON Schema, valide todo dado que vem de fora na borda, e compartilhe o mesmo schema entre quem produz e quem consome. Use uma biblioteca pronta, ligue allErrors, e devolva o erro com caminho e motivo. É a diferença entre pegar o problema no 400 da entrada ou caçá-lo num 500 três serviços depois.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil