Validação com JSON Schema: O Guia Definitivo
O JSON Schema é um vocabulário para anotar e validar documentos JSON. Fornece um contrato para os seus dados — definindo que forma devem ter, que tipos são aceitáveis e quais campos são obrigatórios. Se trabalha com APIs, ficheiros de configuração ou quaisquer dados estruturados, o JSON Schema é uma ferramenta essencial no seu arsenal.
Porquê Utilizar JSON Schema?
Sem validação, os dados JSON são uma incógnita. Pode receber um campo de idade como string, um e-mail em falta ou uma data no formato errado. O JSON Schema deteta estes problemas na fronteira, antes que dados incorretos se propaguem pelo seu sistema.
Benefícios principais:
- Imposição de contratos de API: Validar corpos de pedido e resposta automaticamente
- Documentação: O schema serve como documentação viva para as suas estruturas de dados
- Geração de código: As ferramentas podem gerar tipos, formulários e esquemas de base de dados a partir do JSON Schema
- Testes: Validar fixtures de teste e dados mock contra o schema
Estrutura Básica do Schema
Todo JSON Schema começa com algumas propriedades padrão:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"description": "A registered user in the system",
"type": "object",
"properties": {
"id": { "type": "integer", "minimum": 1 },
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 }
},
"required": ["id", "name", "email"]
}
Utilize o nosso Formatador JSON para embelezar os seus schemas e melhorar a legibilidade antes de os partilhar com a sua equipa.
Restrições de Tipo
O JSON Schema suporta seis tipos primitivos:
| Tipo | Descrição | Exemplo |
|---|---|---|
string | Dados de texto | "hello" |
number | Qualquer valor numérico | 3.14 |
integer | Apenas números inteiros | 42 |
boolean | Verdadeiro ou falso | true |
array | Lista ordenada | [1, 2, 3] |
object | Pares chave-valor | {"key": "value"} |
null | Valor nulo | null |
Restrições de String
{
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9]+$",
"format": "email"
}
Os formatos integrados incluem: email, uri, date, date-time, ipv4, ipv6, uuid e hostname.
Restrições Numéricas
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0,
"multipleOf": 0.01
}
Validação de Arrays
Os arrays podem ser validados quanto aos seus itens, comprimento e unicidade:
{
"type": "array",
"items": { "type": "string", "format": "email" },
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
Para validação de tuplos (arrays de comprimento fixo com tipos específicos por posição):
{
"type": "array",
"prefixItems": [
{ "type": "number" },
{ "type": "string" },
{ "type": "boolean" }
],
"items": false
}
Validação de Objetos
Os objetos suportam validação de propriedades, campos obrigatórios e controlo de propriedades adicionais:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"role": { "enum": ["admin", "editor", "viewer"] }
},
"required": ["name", "role"],
"additionalProperties": false
}
Definir additionalProperties como false é um modo rigoroso que rejeita quaisquer propriedades não definidas no schema. Isto é particularmente útil para APIs onde se pretende detetar erros de digitação nos nomes dos campos.
Palavras-chave de Composição
O JSON Schema suporta a combinação de schemas utilizando operadores lógicos:
allOf (E)
Os dados devem ser válidos contra todos os sub-schemas:
{
"allOf": [
{ "$ref": "#/$defs/baseUser" },
{ "properties": { "role": { "const": "admin" } } }
]
}
oneOf (OU Exclusivo)
Os dados devem ser válidos contra exatamente um dos sub-schemas:
{
"oneOf": [
{ "properties": { "type": { "const": "email" }, "email": { "type": "string" } } },
{ "properties": { "type": { "const": "phone" }, "phone": { "type": "string" } } }
]
}
anyOf (OU)
Os dados devem ser válidos contra pelo menos um dos sub-schemas.
Validação Condicional
As palavras-chave if/then/else permitem validação condicional:
{
"type": "object",
"properties": {
"country": { "type": "string" },
"postalCode": { "type": "string" }
},
"if": {
"properties": { "country": { "const": "US" } }
},
"then": {
"properties": { "postalCode": { "pattern": "^[0-9]{5}(-[0-9]{4})?$" } }
},
"else": {
"properties": { "postalCode": { "pattern": "^[A-Z0-9 -]+$" } }
}
}
Referências e Reutilização
Utilize $ref para referenciar definições reutilizáveis:
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string" }
},
"required": ["street", "city", "country"]
}
},
"type": "object",
"properties": {
"billingAddress": { "$ref": "#/$defs/address" },
"shippingAddress": { "$ref": "#/$defs/address" }
}
}
Validação na Prática
JavaScript (Ajv)
const Ajv = require('ajv');
const ajv = new Ajv();
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) console.log(validate.errors);
Python (jsonschema)
from jsonschema import validate, ValidationError
try:
validate(instance=data, schema=schema)
except ValidationError as e:
print(f"Validation error: {e.message}")
Para validação rápida sem configurar um ambiente de desenvolvimento, cole o seu JSON e schema no nosso Validador JSON.
Exemplo do Mundo Real: Schema de Resposta de API
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"status": { "enum": ["success", "error"] },
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"createdAt": { "type": "string", "format": "date-time" }
},
"required": ["id", "name"]
}
},
"pagination": {
"type": "object",
"properties": {
"page": { "type": "integer", "minimum": 1 },
"perPage": { "type": "integer", "minimum": 1, "maximum": 100 },
"total": { "type": "integer", "minimum": 0 }
}
}
},
"required": ["status", "data"]
}
FAQ
Qual é a diferença entre o JSON Schema draft-07 e o 2020-12?
O Draft 2020-12 introduziu várias melhorias: prefixItems substituiu a forma de tuplo de items, $dynamicRef permite referências mais flexíveis e o suporte a vocabulários permite extensões personalizadas. Para novos projetos, utilize 2020-12. Para compatibilidade com ferramentas mais antigas, o draft-07 ainda é amplamente suportado.
O JSON Schema pode validar JSON aninhado dentro de um campo de string?
Não, diretamente. O JSON Schema valida a estrutura de JSON já analisado. Se um campo contém uma string JSON, seria necessário analisá-la primeiro e validar separadamente. Alguns validadores oferecem validadores de formato personalizados que podem lidar com isto, mas não faz parte do padrão.
Recursos Relacionados
- Formatador JSON — Formatar e embelezar os seus JSON schemas
- Como Validar JSON — Erros comuns de validação JSON e correções
- Padrões de Design de API JSON — Construir melhores APIs REST com JSON