JSON Schema é um vocabulário para descrever a estrutura, as restrições e os tipos de um documento JSON. Permite que você defina exatamente como deve ser um JSON válido — quais chaves são obrigatórias, que tipo cada valor deve ter, quais valores são permitidos — e depois valide automaticamente qualquer documento JSON contra essas regras. Este guia explica o que é JSON Schema, como escrever um e como usá-lo para validar JSON em JavaScript, Python e no navegador.
O que é JSON Schema?
JSON Schema é, em si, um documento JSON. Descreve outro documento JSON da mesma forma que um esquema de banco de dados descreve uma tabela: declara o formato esperado, os tipos e as restrições dos dados. Um JSON Schema diz aos validadores — bibliotecas, APIs, geradores de formulário, IDEs — o que significa «válido» para um JSON específico.
A especificação é mantida em json-schema.org e está atualmente no Draft 2020-12. É usada pelo OpenAPI (o padrão para documentar APIs REST), pelo JSON Forms (geração de UI a partir de schemas), pelo tooling de IDE (o VS Code usa JSON Schema para autocompletar package.json e tsconfig.json) e por incontáveis pipelines de dados internos.
Um exemplo mínimo de JSON Schema
Aqui está um documento JSON representando um usuário, seguido de um schema que descreve sua estrutura esperada:
// O documento JSON a ser validado
{
"id": 42,
"name": "Alice",
"email": "alice@example.com",
"age": 30,
"active": true
}// O JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 },
"active": { "type": "boolean" }
},
"additionalProperties": false
}Esse schema diz: o documento deve ser um objeto; id, name e email são obrigatórios; age deve estar entre 0 e 150 se presente; e nenhuma chave fora das cinco listadas é permitida.
As palavras-chave centrais
type
Especifica o tipo JSON de um valor. Os tipos válidos são "string", "number", "integer", "boolean", "array", "object" e "null". Você pode permitir vários tipos com um array:
{ "type": ["string", "null"] } // o valor pode ser string ou nullproperties
Define o schema de cada chave em um objeto. Cada entrada é, por sua vez, um schema:
{
"type": "object",
"properties": {
"firstName": { "type": "string" },
"lastName": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
}
}required
Um array com nomes de chaves que devem estar presentes no objeto. Uma chave listada em properties mas não em required é opcional — pode estar ausente, mas se estiver presente precisa bater com o schema dela.
items
Define o schema para cada elemento de um array. Este schema exige um array de strings:
{
"type": "array",
"items": { "type": "string" }
}Restrições de string
{
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[a-zA-Z0-9_]+quot; // padrão regex
}Restrições numéricas
{
"type": "number",
"minimum": 0,
"maximum": 1,
"multipleOf": 0.01 // deve ser múltiplo de 0.01
}enum
Restringe um valor a um conjunto fixo de valores permitidos:
{ "enum": ["pending", "active", "suspended", "deleted"] }additionalProperties
Controla se chaves não listadas em properties são permitidas. Coloque false para rejeitar quaisquer chaves inesperadas — útil para contratos de API estritos:
{ "additionalProperties": false }Um exemplo real de JSON Schema
Aqui está um schema para um produto em uma API de e-commerce — do tipo que você veria numa definição OpenAPI ou num contrato de dados interno:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/product.json",
"title": "Product",
"description": "A product available for purchase",
"type": "object",
"required": ["id", "name", "price", "category"],
"properties": {
"id": {
"type": "integer",
"description": "Unique product identifier"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"price": {
"type": "number",
"minimum": 0,
"description": "Price in USD"
},
"category": {
"type": "string",
"enum": ["electronics", "clothing", "books", "home", "sports"]
},
"tags": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
},
"dimensions": {
"type": "object",
"properties": {
"width": { "type": "number", "minimum": 0 },
"height": { "type": "number", "minimum": 0 },
"depth": { "type": "number", "minimum": 0 }
},
"required": ["width", "height", "depth"]
},
"inStock": { "type": "boolean" }
},
"additionalProperties": false
}Como validar JSON contra um schema
Procurando um validador jsonschema? Os padrões são Ajv (JavaScript), jsonschema (Python) e serviços online como jsonschemavalidator.net. Se precisar do caminho contrário — gerar json schema a partir de um exemplo, ou um json schema a partir de um json — experimente o GenSON em Python ou o transform.tools no navegador. São ferramentas json schema generator que inferem um schema inicial a partir de uma amostra. Depois aperte required, additionalProperties e restrições de valor à mão.
Em JavaScript (Ajv)
Ajv é o validador JSON Schema mais usado no ecossistema JavaScript. Suporta Draft-07 e Draft 2020-12.
npm install ajvimport Ajv from 'ajv';
const ajv = new Ajv();
const schema = {
type: 'object',
required: ['id', 'name', 'email'],
properties: {
id: { type: 'integer' },
name: { type: 'string', minLength: 1 },
email: { type: 'string' },
},
additionalProperties: false,
};
const validate = ajv.compile(schema);
const data = { id: 42, name: 'Alice', email: 'alice@example.com' };
const valid = validate(data);
if (!valid) {
console.error(validate.errors);
} else {
console.log('Valid!');
}ajv.compile(schema) devolve uma função validate reutilizável. Compilar uma vez e chamar o resultado várias vezes é bem mais rápido do que recompilar a cada chamada.
Em JavaScript (navegador, sem dependências)
Para checagens simples de tipo e campo obrigatório sem adicionar dependência, dá para validar manualmente — mas para qualquer coisa além de checagens triviais, use Ajv. A lógica de validação de schema é complexa o bastante para que escrever na mão seja propenso a erros.
Em Python (jsonschema)
pip install jsonschemaimport json
import jsonschema
from jsonschema import validate, ValidationError
schema = {
"type": "object",
"required": ["id", "name", "email"],
"properties": {
"id": {"type": "integer"},
"name": {"type": "string", "minLength": 1},
"email": {"type": "string"},
},
"additionalProperties": False,
}
data = {"id": 42, "name": "Alice", "email": "alice@example.com"}
try:
validate(instance=data, schema=schema)
print("Valid!")
except ValidationError as e:
print(f"Invalid: {e.message}")Validar um arquivo JSON contra um schema
import json
import jsonschema
with open('schema.json') as f:
schema = json.load(f)
with open('data.json') as f:
data = json.load(f)
jsonschema.validate(instance=data, schema=schema)No navegador (fixjson)
Se você precisa conferir se um documento JSON é estruturalmente válido antes de trabalhar com ele — sem escrever código — o validador JSON do fixjson verifica a sintaxe e aponta erros na hora. Cole o seu JSON e qualquer problema de sintaxe aparece inline com a linha e a posição exatas de cada erro.
Para validação completa de schema (checar tipos, campos obrigatórios, restrições), use uma das abordagens baseadas em biblioteca acima, ou uma ferramenta dedicada de teste de schema como jsonschemavalidator.net.
$ref: reutilizando schemas
Schemas reais não definem tudo inline. A palavra-chave $ref permite referenciar outro schema pelo seu $id ou por um caminho JSON Pointer dentro do mesmo documento, mantendo os schemas DRY e componíveis.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"address": {
"type": "object",
"required": ["street", "city", "country"],
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string", "minLength": 2, "maxLength": 2 }
}
}
},
"type": "object",
"properties": {
"billingAddress": { "$ref": "#/$defs/address" },
"shippingAddress": { "$ref": "#/$defs/address" }
}
}$defs é o lugar padrão para definir sub-schemas reutilizáveis em um único arquivo (substituiu definitions no Draft 2019-09).
Combinando schemas: allOf, anyOf, oneOf
JSON Schema tem três palavras-chave de composição para expressar «precisa bater com todos», «precisa bater com pelo menos um» e «precisa bater com exatamente um»:
// allOf: precisa satisfazer todos os schemas listados
{
"allOf": [
{ "type": "object" },
{ "required": ["id"] },
{ "properties": { "id": { "type": "integer" } } }
]
}
// anyOf: precisa satisfazer pelo menos um schema
{
"anyOf": [
{ "type": "string" },
{ "type": "null" }
]
}
// oneOf: precisa satisfazer exatamente um schema (devem ser mutuamente exclusivos)
{
"oneOf": [
{ "properties": { "type": { "const": "circle" } }, "required": ["radius"] },
{ "properties": { "type": { "const": "rectangle" } }, "required": ["width", "height"] }
]
}A palavra-chave format: date-time, email, uri, uuid
Além dos tipos crus, a palavra-chave format do JSON Schema anota strings com sua forma pretendida — um date-time ISO, um endereço de e-mail, um URI, um UUID, um endereço IP, e por aí vai. Assim:
{
"type": "object",
"properties": {
"id": { "type": "string", "format": "uuid" },
"created_at": { "type": "string", "format": "date-time" },
"email": { "type": "string", "format": "email" },
"homepage": { "type": "string", "format": "uri" }
}
}Um detalhe sutil, mas importante: no Draft 2020-12 (e 2019-09), a palavra-chave format é uma anotação por padrão — não impõe o formato a menos que o validador seja configurado para isso. No Draft-07 e anteriores, em alguns validadores era assertion por padrão. Para deixar estrito no Ajv:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv); // registra date-time, email, uri, uuid, etc.
// No 2020-12 você precisa habilitar format assertion no seu meta-schema ou
// passar explicitamente { validateFormats: true }, conforme a versão do Ajv.Valores comuns de format: date-time, date, time, duration, email, idn-email, hostname, ipv4, ipv6, uri, uri-reference, uuid, regex, json-pointer.
Trate format como dica, não como fronteira de segurança — uma string que passa por format: "email" continua sendo input não confiável. Para entregabilidade ou validade real, verifique fora de banda (DNS, mandar e-mail de confirmação, rodar uma regex que você controla).
Erros comuns em JSON Schema
Confundir «properties» com «required»
Listar uma chave em properties não a torna obrigatória. Uma chave em properties define o schema dessa chave se ela aparecer. Para exigir sua presença, é preciso listá-la também em required.
Usar «integer» quando quer dizer «number»
"type": "integer" rejeita 3.14. Se o seu campo pode ser qualquer número (inclusive decimais), use "type": "number".
Esquecer que «additionalProperties» é true por padrão
Por padrão, o JSON Schema permite qualquer propriedade adicional não listada em properties. Isso é intencional — schemas são pensados para ser abertos por padrão, seguindo a Lei de Postel. Se quiser um objeto fechado, defina explicitamente "additionalProperties": false.
Não especificar $schema
Drafts diferentes têm semânticas diferentes. Omitir a palavra-chave $schema deixa os validadores adivinhando que versão usar. Inclua sempre:
{ "$schema": "https://json-schema.org/draft/2020-12/schema" }Tratar validação de JSON Schema como validação de segurança
O JSON Schema valida estrutura e tipos — não é ferramenta de sanitização. Uma string que passa "type": "string" ainda pode conter SQL injection, payloads de XSS ou outro conteúdo malicioso. Validação de schema é o primeiro portão, não uma medida completa de segurança.
JSON Schema e OpenAPI
OpenAPI (antigamente Swagger) usa um subconjunto de JSON Schema para descrever corpos de requisição, corpos de resposta e parâmetros. Se você já escreveu uma spec OpenAPI, já escreveu JSON Schema — embora o OpenAPI use um dialeto modificado, com algumas extensões e restrições.
Isso significa que o conhecimento de JSON Schema se transfere direto para o design de APIs. A seção components/schemas de um documento OpenAPI é uma coleção de JSON Schemas, e ferramentas como Stoplight, Redoc e Swagger UI as transformam automaticamente em documentação interativa.
Trabalhando com Ajv na prática
Duas flags se pagam em qualquer projeto sério:
strict: true(padrão no Ajv moderno) — rejeita palavras-chave desconhecidas e formats desconhecidos no momento da compilação do schema, pegando erros de digitação como"minimun"ou um$schemafaltando antes que deixem passar dados silenciosamente.allErrors: true— coleta todas as falhas de validação em vez de parar na primeira. Combina bem comajv.errorsText()para mensagens voltadas ao usuário.
Para gerar fake JSON a partir de um schema para testes e fixtures, use json-schema-faker: ele percorre o schema e produz valores que casam (tipos, faixas, enums, e até format quando combinado com ajv-formats). Útil para testes baseados em propriedades ou para semear uma UI a partir de um schema.
Gerando um JSON Schema a partir de JSON existente
Se você tem dados JSON e quer gerar um schema inicial a partir deles, várias ferramentas automatizam o processo:
- quicktype.io — infere schemas (e definições de tipo para TypeScript, Go, Python e outros) a partir de JSON de exemplo
- generate-schema (npm) —
generate-schema json schema.json data.json - Python: genson —
pip install genson, depoisSchemaBuilderinfere um schema a partir de um ou mais objetos de exemplo
Schemas gerados são um ponto de partida, não um produto acabado. Eles inferem tipos a partir dos dados de amostra, mas não conhecem as suas regras de negócio — não conseguem inferir que um campo string é um e-mail, ou que um inteiro precisa ser positivo, ou que dois campos são mutuamente exclusivos. Sempre revise e aperte um schema gerado antes de usá-lo em produção.
Perguntas frequentes
Para que serve o JSON Schema?
Para descrever e validar a estrutura de dados JSON — quais chaves são obrigatórias, que tipo cada valor deve ter e quais valores são permitidos. Ele alimenta o OpenAPI, autocomplete em IDE para package.json/tsconfig.json, geração de formulários e contratos de pipeline de dados.
Qual a diferença entre JSON e JSON Schema?
JSON são os dados; JSON Schema é um documento JSON separado que descreve como devem ser dados válidos. Se está começando com o próprio formato, comece por O que é JSON?.
Qual draft de JSON Schema eu devo usar?
Draft 2020-12 é o atual e recomendado para schemas novos; Draft-07 continua comum por causa do amplo suporte de tooling. Sempre declare a versão com $schema para os validadores não terem que adivinhar.
Como valido JSON contra um schema?
Use Ajv em JavaScript, a biblioteca jsonschema em Python (exemplos acima), ou um validador web. Para primeiro confirmar se o JSON é sequer sintaticamente válido, veja Como validar JSON ou rode pelo validador.
O JSON Schema valida format (email, date-time, uri…)?
No Draft 2020-12 / 2019-09, a palavra-chave format é anotação por padrão — os validadores só impõem quando configurados para isso. Com Ajv, registre o ajv-formats e habilite a format assertion para de fato rejeitar valores malformados.
Conclusão
O JSON Schema transforma documentação informal («esse campo deveria ser um número») em um contrato verificável por máquina que os validadores podem impor de forma consistente entre linguagens, times e sistemas. O vocabulário central — type, properties, required, items, enum — cobre a grande maioria dos casos reais. Recursos mais avançados como $ref, palavras-chave de composição e format dão conta do resto.
Comece com um schema mínimo que imponha apenas o que você realmente precisa impor. Adicione restrições aos poucos conforme seu entendimento dos dados se solidifica. Um schema que rejeita dados válidos é pior do que não ter schema.
Se o JSON que você está validando tem erros de sintaxe antes mesmo de chegar ao validador de schema, conserte isso primeiro — um validador de schema exige JSON sintaticamente correto na entrada. Quando o JSON estiver limpo, valide-o e depois aplique seu schema.