Validación con JSON Schema: La Guía Definitiva
JSON Schema es un vocabulario para anotar y validar documentos JSON. Proporciona un contrato para tus datos — definiendo qué forma deben tener, qué tipos son aceptables y qué campos son requeridos. Si trabajas con APIs, archivos de configuración o cualquier dato estructurado, JSON Schema es una herramienta esencial en tu arsenal.
¿Por Qué Usar JSON Schema?
Sin validación, los datos JSON son una incógnita. Podrías recibir un campo de edad como cadena, un email faltante o una fecha en el formato incorrecto. JSON Schema detecta estos problemas en la frontera, antes de que los datos incorrectos se propaguen por tu sistema.
Beneficios clave:
- Cumplimiento de contratos de API: Valida automáticamente los cuerpos de solicitud y respuesta
- Documentación: El esquema sirve como documentación viva para tus estructuras de datos
- Generación de código: Las herramientas pueden generar tipos, formularios y esquemas de base de datos desde JSON Schema
- Testing: Valida fixtures de prueba y datos mock contra el esquema
Estructura Básica del Schema
Todo JSON Schema comienza con algunas propiedades estándar:
{
"$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"]
}
Usa nuestro Formateador JSON para embellecer tus esquemas y mejorar la legibilidad antes de compartirlos con tu equipo.
Restricciones de Tipo
JSON Schema soporta seis tipos primitivos:
| Tipo | Descripción | Ejemplo |
|---|---|---|
string | Datos de texto | "hello" |
number | Cualquier valor numérico | 3.14 |
integer | Solo números enteros | 42 |
boolean | Verdadero o falso | true |
array | Lista ordenada | [1, 2, 3] |
object | Pares clave-valor | {"key": "value"} |
null | Valor nulo | null |
Restricciones de String
{
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9]+$",
"format": "email"
}
Los formatos incorporados incluyen: email, uri, date, date-time, ipv4, ipv6, uuid y hostname.
Restricciones Numéricas
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0,
"multipleOf": 0.01
}
Validación de Arrays
Los arrays pueden ser validados por sus elementos, longitud y unicidad:
{
"type": "array",
"items": { "type": "string", "format": "email" },
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
Para validación de tuplas (arrays de longitud fija con tipos específicos por posición):
{
"type": "array",
"prefixItems": [
{ "type": "number" },
{ "type": "string" },
{ "type": "boolean" }
],
"items": false
}
Validación de Objetos
Los objetos soportan validación de propiedades, campos requeridos y control de propiedades adicionales:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"role": { "enum": ["admin", "editor", "viewer"] }
},
"required": ["name", "role"],
"additionalProperties": false
}
Establecer additionalProperties como false es un modo estricto que rechaza cualquier propiedad no definida en el esquema. Esto es particularmente útil para APIs donde quieres detectar errores tipográficos en nombres de campos.
Palabras Clave de Composición
JSON Schema soporta la combinación de esquemas usando operadores lógicos:
allOf (AND)
Los datos deben ser válidos contra todos los subesquemas:
{
"allOf": [
{ "$ref": "#/$defs/baseUser" },
{ "properties": { "role": { "const": "admin" } } }
]
}
oneOf (XOR)
Los datos deben ser válidos contra exactamente uno de los subesquemas:
{
"oneOf": [
{ "properties": { "type": { "const": "email" }, "email": { "type": "string" } } },
{ "properties": { "type": { "const": "phone" }, "phone": { "type": "string" } } }
]
}
anyOf (OR)
Los datos deben ser válidos contra al menos uno de los subesquemas.
Validación Condicional
Las palabras clave if/then/else habilitan la validación 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 -]+$" } }
}
}
Referencias y Reutilización
Usa $ref para referenciar definiciones reutilizables:
{
"$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" }
}
}
Validación en la Práctica
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 validación rápida sin configurar un entorno de desarrollo, pega tu JSON y esquema en nuestro Validador JSON.
Ejemplo del Mundo Real: Schema de Respuesta 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
¿Cuál es la diferencia entre JSON Schema draft-07 y 2020-12?
El draft 2020-12 introdujo varias mejoras: prefixItems reemplazó la forma de tupla de items, $dynamicRef permite referencias más flexibles, y el soporte de vocabulario permite extensiones personalizadas. Para proyectos nuevos, usa 2020-12. Para compatibilidad con herramientas antiguas, draft-07 todavía tiene amplio soporte.
¿Puede JSON Schema validar JSON anidado dentro de un campo de tipo string?
No, directamente. JSON Schema valida la estructura del JSON parseado. Si un campo contiene una cadena JSON, necesitarías parsearla primero y validarla por separado. Algunos validadores ofrecen validadores de formato personalizados que pueden manejar esto, pero no es parte del estándar.
Recursos Relacionados
- Formateador JSON — Formatea y embellece tus esquemas JSON
- Cómo Validar JSON — Errores comunes de validación JSON y sus soluciones
- Patrones de Diseño de APIs JSON — Construyendo mejores APIs REST con JSON