JSON Schema: What It Is and How to Use It
Learn JSON Schema from scratch. Understand types, constraints, composition keywords, $ref, and see a complete practical example for API validation.
O Que É JSON Schema?
JSON Schema é um vocabulário que permite descrever a estrutura dos dados JSON. Pense nisso como um contrato: ele define quais campos um documento JSON deve ter, quais tipos esses campos devem ser e quais restrições devem ser atendidas. Quando um documento está em conformidade com seu esquema, ele é válido. Quando não está, um validador informa exatamente o que deu errado.
Isso é importante porque o JSON em si é estruturalmente permissivo. Nada na especificação JSON impede uma API de retornar uma string onde você espera um número ou omitir um campo obrigatório. O JSON Schema fecha essa lacuna.
Por Que o JSON Schema É Importante
- Contratos de API. Defina exatamente o que sua API espera e retorna. Tanto as equipes de cliente quanto de servidor podem validar cargas úteis de forma independente.
- Validação de dados. Capture dados malformados na fronteira — em envios de formulários, cargas úteis de webhook, arquivos de configuração ou gravações em banco de dados.
- Documentação. Um esquema é uma documentação legível por máquina. Ferramentas podem gerar documentos legíveis por humanos, formulários e até dados simulados a partir dele.
- Geração de código. Gere interfaces TypeScript, structs Go ou dataclasses Python diretamente do seu esquema.
O Básico: Tipo, Propriedades, Obrigatório
Todo JSON Schema começa com type. Isso informa ao validador que tipo de valor esperar no nível superior:
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "O nome completo do usuário"
},
"age": {
"type": "integer",
"description": "Idade em anos"
}
},
"required": ["name"]
}
Este esquema diz: "Eu espero um objeto JSON com uma propriedade name (string, obrigatória) e uma propriedade age opcional (inteiro)." Qualquer objeto que não contenha name ou forneça um name não-string é inválido.
Todos os Tipos de JSON Schema
O JSON Schema suporta sete tipos primitivos. Aqui está cada um com um exemplo de esquema mínimo:
| Tipo | Valores Válidos | Exemplo de Esquema |
|---|---|---|
string | "hello", "" | {"type": "string"} |
number | 3.14, -1, 0 | {"type": "number"} |
integer | 42, -7 | {"type": "integer"} |
boolean | true, false | {"type": "boolean"} |
null | null | {"type": "null"} |
object | {"key": "value"} | {"type": "object", "properties": {...}} |
array | [1, 2, 3] | {"type": "array", "items": {...}} |
Objetos em Detalhe
Use properties para definir campos esperados, required para listar os obrigatórios e additionalProperties para controlar se campos extras são permitidos:
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "email"],
"additionalProperties": false
}
Definir additionalProperties: false rejeita qualquer objeto que contenha chaves não listadas em properties. Isso é útil para contratos de API rigorosos.
Arrays em Detalhe
Use items para definir como cada elemento deve ser, e minItems / maxItems para restringir o comprimento:
{
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
Isso aceita um array de 1 a 10 strings únicas. Um array vazio ou um array com duplicatas falharia na validação.
Restrições e Palavras-Chave de Validação
Além dos tipos básicos, o JSON Schema fornece restrições detalhadas para cada tipo:
Restrições de String
| Palavra-Chave | Descrição | Exemplo |
|---|---|---|
minLength | Número mínimo de caracteres | "minLength": 1 |
maxLength | Número máximo de caracteres | "maxLength": 255 |
pattern | Regex que a string deve corresponder | "pattern": "^[A-Z]{2}\\\\d{4}$" |
format | Dica de formato semântico | "format": "email" |
enum | Valores permitidos | "enum": ["active", "inactive"] |
Restrições de Número
| Palavra-Chave | Descrição | Exemplo |
|---|---|---|
minimum | O valor deve ser >= a este | "minimum": 0 |
maximum | O valor deve ser <= a este | "maximum": 100 |
exclusiveMinimum | O valor deve ser > a este | "exclusiveMinimum": 0 |
exclusiveMaximum | O valor deve ser < a este | "exclusiveMaximum": 1000 |
multipleOf | O valor deve ser divisível por este | "multipleOf": 0.01 |
Combinando Esquemas: allOf, anyOf, oneOf, not
As palavras-chave de composição permitem que você construa esquemas complexos a partir de esquemas mais simples:
- allOf — Os dados devem ser válidos em relação a todos os esquemas listados. Usado para combinar várias restrições ou estender um esquema base.
- anyOf — Os dados devem ser válidos em relação a pelo menos um dos esquemas listados. Útil para campos que aceitam múltiplos formatos.
- oneOf — Os dados devem ser válidos em relação a exatamente um dos esquemas listados. Bom para uniões discriminadas.
- not — Os dados devem não ser válidos em relação ao esquema dado.
{
"oneOf": [
{
"type": "object",
"properties": {
"type": { "const": "email" },
"address": { "type": "string", "format": "email" }
},
"required": ["type", "address"]
},
{
"type": "object",
"properties": {
"type": { "const": "phone" },
"number": { "type": "string", "pattern": "^\\\\+?[0-9]{7,15}$" }
},
"required": ["type", "number"]
}
]
}
Este esquema aceita um contato de email ou um contato telefônico, mas não ambos — uma maneira limpa de modelar uniões marcadas.
Reutilização com $ref
Os esquemas se tornam repetitivos rapidamente. A palavra-chave $ref permite que você faça referência a uma definição reutilizável:
{
"type": "object",
"properties": {
"billing_address": { "$ref": "#/$defs/address" },
"shipping_address": { "$ref": "#/$defs/address" }
},
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zip": { "type": "string", "pattern": "^[0-9]{5}(-[0-9]{4})?$" }
},
"required": ["street", "city", "zip"]
}
}
}
Tanto billing_address quanto shipping_address compartilham a mesma estrutura sem duplicação. A seção $defs (chamada de definitions em rascunhos mais antigos) é o lugar convencional para armazenar esquemas reutilizáveis.
Exemplo Completo: Validação de Registro de Usuário
Aqui está um esquema do mundo real para validar uma carga útil de registro de usuário. Ele usa a maioria dos recursos que cobrimos:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "UserRegistration",
"description": "Esquema para o endpoint POST /api/register",
"type": "object",
"properties": {
"username": {
"type": "string",
"minLength": 3,
"maxLength": 30,
"pattern": "^[a-zA-Z0-9_]+$",
"description": "Nome de usuário alfanumérico, 3-30 caracteres"
},
"email": {
"type": "string",
"format": "email",
"maxLength": 254
},
"password": {
"type": "string",
"minLength": 8,
"maxLength": 128,
"description": "Pelo menos 8 caracteres"
},
"age": {
"type": "integer",
"minimum": 13,
"maximum": 150
},
"role": {
"type": "string",
"enum": ["user", "moderator"],
"default": "user"
},
"acceptedTerms": {
"type": "boolean",
"const": true
},
"tags": {
"type": "array",
"items": { "type": "string", "maxLength": 20 },
"maxItems": 5,
"uniqueItems": true
}
},
"required": ["username", "email", "password", "acceptedTerms"],
"additionalProperties": false
}
Observe como cada campo tem restrições claras e aplicáveis. Um validador rejeitará um nome de usuário de 2 caracteres, uma idade abaixo de 13, tags duplicadas ou quaisquer campos extras não listados no esquema.
Experimente você mesmo: Cole qualquer JSON e gere um esquema automaticamente com nosso Gerador de JSON Schema.
JSON Schema no Mundo Real
OpenAPI / Swagger
OpenAPI usa JSON Schema (com algumas extensões) para definir corpos de requisição, formatos de resposta e parâmetros de consulta. Cada bloco schema em uma especificação OpenAPI é um JSON Schema. Se você escreve documentos OpenAPI, já escreve JSON Schema.
Validação de Formulários
Bibliotecas como react-jsonschema-form e ajv (o validador de JSON Schema mais rápido para JavaScript) usam esquemas para gerar e validar formulários em tempo de execução. Defina seu esquema uma vez, e tanto o backend quanto o frontend podem validar de acordo com as mesmas regras.
Esquemas de Banco de Dados
O MongoDB suporta validação de JSON Schema no nível da coleção. Você pode definir um validador $jsonSchema que rejeita qualquer documento que não esteja em conformidade com seu esquema ao inserir ou atualizar.
Arquivos de Configuração
O VS Code, ESLint e muitas outras ferramentas usam JSON Schema para validar seus arquivos de configuração. Aquela autocompletação que você recebe ao editar tsconfig.json? É alimentada por JSON Schema.
Comparação de Versões de Rascunho
O JSON Schema evoluiu através de vários rascunhos. Aqui estão os que você encontrará:
| Rascunho | Ano | Principais Adições | Status |
|---|---|---|---|
| Draft-04 | 2013 | Vocabulário central, $ref, tipos básicos | Legado (ainda amplamente utilizado) |
| Draft-06 | 2017 | const, contains, propertyNames | Legado |
| Draft-07 | 2018 | if/then/else, readOnly, writeOnly | Amplamente suportado |
| 2019-09 | 2019 | $defs, unevaluatedProperties, dependentRequired | Suportado por validadores principais |
| 2020-12 | 2020 | prefixItems (substitui a validação de tuplas), $ref dinâmico | Atual / recomendado |
Para novos projetos, use 2020-12. Se você precisar de máxima compatibilidade com ferramentas existentes, Draft-07 é a escolha segura — possui suporte quase universal de bibliotecas.
Erros Comuns a Evitar
- Esquecer
required. Propriedades definidas empropertiessão opcionais por padrão. Se um campo deve estar presente, liste-o emrequired. - Confundir
numbereinteger.numberaceita decimais;integernão. Useintegerpara IDs, contagens e outros valores inteiros. - Restringir demais muito cedo. Comece com o esquema mínimo que captura erros reais. Você sempre pode apertar as restrições mais tarde — afrouxá-las é uma mudança quebradora.
- Não usar
$ref. Duplicar o mesmo sub-esquema em vários lugares é um pesadelo de manutenção. Extraia estruturas compartilhadas em$defs. - Ignorar a validação de
format. Por padrão, a maioria dos validadores trataformatcomo uma anotação, não como uma restrição. Você precisa habilitar explicitamente a validação de formato (por exemplo,ajv.addFormat()ou passando{ validateFormats: true }).
Experimente você mesmo: Gere um esquema a partir de qualquer amostra JSON com nosso Gerador de JSON Schema, e depois personalize as restrições para atender às suas necessidades.