JSON Schema: Como Validar e Documentar Dados
JSON Schema é o padrão para descrever a estrutura de qualquer JSON. É a base do OpenAPI/Swagger, valida entrada de APIs, configs e mensagens. Veja a sintaxe Draft 2020-12, validação com AJV/Pydantic, geração de tipos TypeScript e comparativo com Zod, Yup e Joi.
Por Vitor Morais
Fundador do MochaLabz ·
Formate seu JSON antes de validar
Identifique erros de sintaxe primeiro — depois aplique o schema com tranquilidade.
Usar formatador de JSON →JSON Schema é o padrão para descrever a estrutura, os tipos e as restrições de qualquer documento JSON — usando o próprio JSON como linguagem. É a fundação por trás do OpenAPI/Swagger, do contrato de várias APIs públicas (GitHub, Stripe, Twilio) e da validação em ambientes que vão de Node.js a Pydantic. Este guia cobre a sintaxe completa do Draft 2020-12, validação prática em três stacks, integração com OpenAPI e como comparar com bibliotecas modernas como Zod e Pydantic.
O que é JSON Schema na prática
Imagine que sua API recebe esta requisição:
POST /usuarios
{
"nome": "Ana",
"email": "ana@example.com",
"idade": 30
}Sem validação, você precisa checar manualmente: tem nome? é string? tem email? é formato válido? idade é número? está entre 0 e 150? JSON Schema permite descrever todas essas regras de uma vez:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["nome", "email"],
"additionalProperties": false,
"properties": {
"nome": { "type": "string", "minLength": 2, "maxLength": 100 },
"email": { "type": "string", "format": "email" },
"idade": { "type": "integer", "minimum": 0, "maximum": 150 },
"ativo": { "type": "boolean", "default": true }
}
}Um validador roda esse schema contra a entrada e retorna ok ou uma lista de erros precisos — sem você escrever uma linha de if.
Os tipos primitivos suportados
| Critério | Restrições mais usadas |
|---|---|
| string | minLength, maxLength, pattern (regex), format, enum |
| number / integer | minimum, maximum, exclusiveMinimum, multipleOf |
| boolean | true / false (sem restrições adicionais) |
| null | aceita só null |
| array | items, minItems, maxItems, uniqueItems, contains |
| object | properties, required, additionalProperties, dependentRequired |
Strings: format e pattern
A propriedade format ativa validação semântica extra (depende do validador suportar — AJV com ajv-formats cobre todos):
{
"type": "string",
"format": "email" // email, uri, uuid, date, date-time,
} // ipv4, ipv6, hostname, regex, etc.
// Pattern via regex
{
"type": "string",
"pattern": "^\\+?[1-9]\\d{1,14}$" // E.164 phone format
}
// Enum (lista fixa de valores aceitos)
{
"type": "string",
"enum": ["pendente", "ativo", "cancelado"]
}Objects: required, properties, additionalProperties
{
"type": "object",
"required": ["id", "email"],
"additionalProperties": false, // rejeita propriedades extras
"properties": {
"id": { "type": "string", "format": "uuid" },
"email": { "type": "string", "format": "email" },
"telefone": { "type": "string", "pattern": "^\\d{10,11}$" },
"endereco": { "$ref": "#/definitions/endereco" }
},
"definitions": {
"endereco": {
"type": "object",
"required": ["cep", "rua"],
"properties": {
"cep": { "type": "string", "pattern": "^\\d{5}-?\\d{3}$" },
"rua": { "type": "string" },
"numero": { "type": "integer" },
"cidade": { "type": "string" }
}
}
}
}additionalProperties: false em produção
Sem additionalProperties: false, propriedades extras passam silenciosamente. Em APIs públicas, isso pode virar vetor de ataque (request smuggling, parameter pollution). Sempre defina explicitamente.
Arrays e items
// Array de strings
{
"type": "array",
"items": { "type": "string", "minLength": 1 },
"minItems": 1,
"maxItems": 100,
"uniqueItems": true
}
// Array de objetos (para listas de pedidos, produtos, etc.)
{
"type": "array",
"items": {
"type": "object",
"required": ["id", "valor"],
"properties": {
"id": { "type": "string" },
"valor": { "type": "number", "minimum": 0 }
}
}
}
// Tupla (Draft 2020-12 usa prefixItems)
{
"type": "array",
"prefixItems": [
{ "type": "string" },
{ "type": "number" },
{ "type": "boolean" }
],
"items": false // sem itens extras
}Combinando schemas: allOf, anyOf, oneOf, not
Para validar variantes, unions e composição:
| Critério | Comportamento | Caso de uso |
|---|---|---|
| allOf | Casa em TODOS os schemas listados | Combinar / estender schemas |
| anyOf | Casa em AO MENOS UM | Variantes opcionais |
| oneOf | Casa em EXATAMENTE UM | Discriminar entre variantes mutuamente exclusivas |
| not | NÃO casa no schema interno | Excluir formatos específicos |
// Pagamento pode ser cartão OU boleto OU pix (oneOf)
{
"oneOf": [
{
"type": "object",
"required": ["tipo", "numero_cartao"],
"properties": {
"tipo": { "const": "cartao" },
"numero_cartao": { "type": "string", "pattern": "^\\d{16}$" }
}
},
{
"type": "object",
"required": ["tipo", "linha_digitavel"],
"properties": {
"tipo": { "const": "boleto" },
"linha_digitavel": { "type": "string" }
}
},
{
"type": "object",
"required": ["tipo", "chave_pix"],
"properties": {
"tipo": { "const": "pix" },
"chave_pix": { "type": "string" }
}
}
]
}Validação em Node.js com AJV
AJV é o validador JSON Schema mais usado e mais rápido em Node.js. Compila o schema para JavaScript otimizado uma vez, depois apenas executa:
// npm install ajv ajv-formats
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({
allErrors: true, // retorna TODOS os erros, não para no primeiro
removeAdditional: true, // remove propriedades extras (limpa dados)
useDefaults: true, // aplica "default" nos campos faltantes
});
addFormats(ajv); // ativa "format": "email", "date", etc.
const schema = {
type: 'object',
required: ['nome', 'email'],
additionalProperties: false,
properties: {
nome: { type: 'string', minLength: 2 },
email: { type: 'string', format: 'email' },
idade: { type: 'integer', minimum: 0, default: 18 },
},
};
const validate = ajv.compile(schema); // compila uma vez
function handleRequest(body) {
const valid = validate(body);
if (!valid) {
return { error: 400, details: validate.errors };
}
// body agora está limpo e tipado
return processar(body);
}Validação em Python com Pydantic
Pydantic é o padrão atual em Python para validação de dados. Não usa JSON Schema diretamente — define schemas via classes Python — mas gera JSON Schema automaticamente:
from pydantic import BaseModel, EmailStr, Field
from typing import Optional
class Usuario(BaseModel):
nome: str = Field(..., min_length=2, max_length=100)
email: EmailStr
idade: Optional[int] = Field(None, ge=0, le=150)
ativo: bool = True
# Validação direta
u = Usuario(nome="Ana", email="ana@example.com", idade=30)
# Geração de JSON Schema
print(Usuario.model_json_schema())
# Saída JSON Schema válido (Draft 2020-12)Para validação de JSON Schema puro em Python, use jsonschema ou fastjsonschema.
JSON Schema dentro do OpenAPI / Swagger
OpenAPI 3.1 (lançado em 2021) finalmente unificou com JSON Schema Draft 2020-12 — antes usava um subset modificado. Vantagem: o mesmo schema serve para documentar API e validar requisições:
# openapi.yaml (OpenAPI 3.1)
openapi: 3.1.0
info:
title: API Usuários
version: 1.0.0
paths:
/usuarios:
post:
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UsuarioCreate'
components:
schemas:
UsuarioCreate:
type: object
required: [nome, email]
additionalProperties: false
properties:
nome: { type: string, minLength: 2, maxLength: 100 }
email: { type: string, format: email }
idade: { type: integer, minimum: 0, maximum: 150 }Ferramentas populares: Swagger UI (docs interativos), Redoc (docs estáticos bonitos), Spectral (linter de OpenAPI), Prism (mock server baseado no schema).
Geração automática de tipos TypeScript
Mantenha o schema como fonte de verdade e gere tipos do editor:
# json-schema-to-typescript
npx json-schema-to-typescript schema.json > types.ts
# Saída:
# export interface Usuario {
# nome: string;
# email: string;
# idade?: number;
# ativo?: boolean;
# }
# Para gerar a partir de OpenAPI completo:
npx openapi-typescript ./openapi.yaml -o ./types.ts
# Resultado: tipos sincronizados com a API,
# IntelliSense funciona, refactoring quebra build.Fluxo recomendado
1. Schema JSON é a fonte da verdade.
2. Backend valida com AJV/Pydantic usando o schema.
3. Frontend gera tipos TypeScript a partir do mesmo schema.
4. Documentação OpenAPI usa o mesmo schema.
5. Mudou o schema → tudo se atualiza junto.
JSON Schema vs Zod vs Yup vs Joi
| Critério | Linguagem | Tipo de DSL | Quando usar |
|---|---|---|---|
| JSON Schema | Agnóstico | JSON | Contratos cross-stack, OpenAPI, padrão público |
| Zod | TypeScript | Fluent (chainable) | Apps TS modernos, Next.js, tRPC |
| Yup | JavaScript | Fluent (chainable) | Validação de forms (Formik, Final Form) |
| Joi | JavaScript | Fluent (chainable) | Backend Node clássico (Hapi, Express) |
| Pydantic | Python | Classes Python | FastAPI, validação Python em geral |
| Valibot | TypeScript | Functional | Apps TS com bundle size crítico |
Em 2026, é comum ter dois níveis: Zod (ou Valibot) no front para UX rápida e tipos primorosos, JSON Schema no contrato público (OpenAPI) para portabilidade. Bibliotecas como zod-to-json-schema e json-schema-to-zod ponteiam os dois mundos.
Casos de uso menos óbvios
- Validar package.json: npm publica schema oficial; VS Code dá autocomplete.
- GitHub Actions workflows: schema oficial da GitHub valida YAML antes do push.
- Configs de Kubernetes / Helm: CRDs têm JSON Schema embutido.
- Mensagens em Kafka / RabbitMQ: validar payload antes de processar.
- Forms dinâmicos: renderizar UI a partir de um schema (React JSON Schema Form).
- Mocks e fixtures: ferramentas como
json-schema-fakergeram dados de exemplo a partir do schema.
Performance: AJV em produção
AJV em Node.js valida tipicamente entre 100 mil e 1 milhão de validações por segundo (depende do tamanho/complexidade do schema). Para APIs em alta escala:
- Compile o schema uma vez no boot da aplicação.
- Reutilize a função compilada em todas as requisições.
- Para microserviços muito leves, considere jsonschema-rs (Rust, ainda mais rápido).
- Use
removeAdditional: truepara limpar dados em vez de validar e depois saneitizar.
Erros comuns ao trabalhar com JSON Schema
Anti-padrões frequentes
- Esquecer additionalProperties: false — propriedades extras passam silenciosamente.
- Não definir required: campos vazios passam como válidos.
- Compilar o schema a cada requisição: throughput cai 100×. Compile uma vez no boot.
- Misturar drafts diferentes (Draft 7 com Draft 2020-12): incompatibilidades sutis.
- Schema sem $id e $schema: dificulta cache e interoperabilidade.
- Ignorar mensagens de erro do AJV: log decente acelera debug enormemente.
Checklist do JSON Schema bem feito
- ✅ Declara $schema (URL do draft, ex: Draft 2020-12).
- ✅ type definido em todo schema (object, array, string, ...).
- ✅ required listado nas propriedades obrigatórias.
- ✅ additionalProperties: false em objects estritos.
- ✅ format usado para email, uri, uuid, date, date-time.
- ✅ minLength/maxLength em strings que têm limite real.
- ✅ minimum/maximum em números.
- ✅ Schemas reutilizáveis em $defs (ou definitions, draft 7).
- ✅ Validador compilado uma vez, reutilizado em produção.
- ✅ Tipos TypeScript gerados automaticamente do schema.
- ✅ Documentação OpenAPI usa o mesmo schema.
- ✅ Suite de testes cobre casos válidos e inválidos.
Perguntas frequentes
O que é JSON Schema?+
JSON Schema é uma especificação para descrever a estrutura, os tipos e as restrições de documentos JSON — usando o próprio JSON. Permite validar entrada de APIs, configurações, mensagens em filas, contratos entre microserviços. É a base do OpenAPI/Swagger e tem suporte em todas as linguagens modernas.
Qual a diferença entre JSON Schema, Zod, Yup e Joi?+
JSON Schema é padrão aberto (RFC) descrito em JSON, agnóstico a linguagem — ótimo para contratos cross-stack e OpenAPI. Zod, Yup e Joi são bibliotecas TypeScript/JavaScript com DSL própria (mais ergonômica em código). Vantagens das libs: melhor inferência de tipos no editor, mensagens de erro customizáveis, encadeamento fluente. Vantagens do JSON Schema: portabilidade, padrão de mercado, OpenAPI nativo. Em 2026 é comum usar Zod no front + JSON Schema no contrato API público.
Qual versão de JSON Schema usar em 2026?+
Draft 2020-12 é a versão mais recente e estável, recomendada para projetos novos. Draft 7 ainda é amplamente suportado. OpenAPI 3.1 finalmente alinhou com Draft 2020-12 (antes usava um subset modificado). Para validar JSON em APIs novas, use Draft 2020-12; para integrar com sistemas legados, confirme qual draft eles esperam.
JSON Schema valida tipos em runtime ou em build?+
Em runtime — diferente de TypeScript, que é checado em build e desaparece em runtime. JSON Schema valida o dado real no momento da requisição, garantindo que o JSON recebido cumpre o contrato. Por isso é complemento, não substituto, de TypeScript: TS dá segurança no código que VOCÊ escreve, JSON Schema dá segurança no JSON que vem de FORA.
Posso gerar tipos TypeScript a partir de um JSON Schema?+
Sim, e essa é uma das melhores integrações. Ferramentas como json-schema-to-typescript ou quicktype.io geram interfaces TypeScript automaticamente. No fluxo ideal: schema é a fonte de verdade, TypeScript é gerado, validador (AJV) usa o mesmo schema. Resultado: contrato único, sincronizado entre validação runtime e tipos do editor.
Como JSON Schema lida com unions e oneOf vs anyOf vs allOf?+
anyOf: vale se ao menos um schema casa. oneOf: vale se exatamente um casa (mais estrito). allOf: vale se TODOS casam (combina schemas, ótimo para extensão). Para discriminar entre tipos diferentes (union types), use oneOf com discriminator (no OpenAPI). Para variantes opcionais de um mesmo tipo, use anyOf.
Posso usar JSON Schema para validar configs YAML?+
Sim. YAML é equivalente a JSON em termos de estrutura — qualquer YAML pode ser convertido para JSON e validado pelo mesmo schema. Por isso você vê schemas JSON Schema sendo usados para validar arquivos como package.json, kubernetes.yaml, GitHub Actions workflows. VS Code suporta nativamente: declare $schema no topo e ganhe autocomplete.
Quão lento é validar com JSON Schema em produção?+
Validadores compilados (AJV, fastify-validator, jsonschema-rs em Rust) são muito rápidos — milhares a centenas de milhares de validações por segundo, dependendo do tamanho do schema. AJV em particular usa code generation: compila o schema para JS otimizado uma vez, depois apenas executa. Para APIs em alta escala, validar JSON na entrada custa tipicamente menos de 1 ms por requisição.
Continue lendo
O que é JSON? Guia Completo com Exemplos em 6 Linguagens
JSON é o formato de dados mais usado na web. Aprenda a sintaxe, os 6 tipos de dados, parsing em JavaScript, Python, Go, Java, PHP e Ruby, JSON5/JSONC, erros comuns e boas práticas.
Minificar JSON: Performance Real, Compressão e Quando Vale (2026)
Quando minificar JSON faz diferença real, impacto na performance de APIs, gzip vs brotli vs zstd, alternativas binárias (MessagePack, CBOR, Protobuf) e benchmarks honestos.
Como Converter JSON para CSV em JavaScript (2026): Guia Completo com Código
Guia definitivo de conversão JSON → CSV em JavaScript: abordagens manuais, PapaParse, edge cases com arrays aninhados, encoding UTF-8 com BOM e exemplos prontos em Node.js e browser.
Open Graph Protocol: Guia Completo 2026 (Facebook, LinkedIn, WhatsApp)
Guia definitivo de Open Graph: tags essenciais, og:type por tipo de conteúdo, dimensões corretas de og:image por rede, implementação em Next.js/WordPress/HTML puro, debug por plataforma e os 7 erros que destroem o preview.