← Todos los artículos

¿Qué es JSON Schema? Una guía práctica con ejemplos

JSON Schema es un vocabulario para describir la estructura y restricciones de los datos JSON. Aprende las palabras clave principales, ve ejemplos reales y valida JSON en JavaScript, Python y tu navegador.

JSON Schema es un vocabulario para describir la estructura, las restricciones y los tipos de un documento JSON. Te permite definir exactamente cómo debe ser un JSON válido — qué claves son obligatorias, qué tipo debe tener cada valor, qué valores están permitidos — y luego validar automáticamente cualquier documento JSON contra esas reglas. Esta guía explica qué es JSON Schema, cómo escribir uno y cómo usarlo para validar JSON en JavaScript, Python y el navegador.

¿Qué es JSON Schema?

JSON Schema es, en sí mismo, un documento JSON. Describe otro documento JSON de la misma forma que un esquema de base de datos describe una tabla: declara la forma esperada, los tipos y las restricciones de los datos. Un JSON Schema le dice a los validadores — bibliotecas, APIs, generadores de formularios, IDEs — qué significa «válido» para una pieza concreta de JSON.

La especificación se mantiene en json-schema.org y actualmente va por el Draft 2020-12. La usan OpenAPI (el estándar para documentar APIs REST), JSON Forms (generación de UI a partir de esquemas), herramientas de IDE (VS Code usa JSON Schema para potenciar el autocompletado de package.json y tsconfig.json) e innumerables pipelines de datos internos.

Un ejemplo mínimo de JSON Schema

Aquí tienes un documento JSON que representa un usuario, seguido de un esquema que describe la estructura esperada:

// El documento JSON que se valida
{
  "id": 42,
  "name": "Alice",
  "email": "alice@example.com",
  "age": 30,
  "active": true
}
// El 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
}

Este esquema dice: el documento debe ser un objeto; id, name y email son obligatorios; age, si está presente, debe estar entre 0 y 150; y no se permiten claves distintas a las cinco enumeradas.

Las palabras clave principales

type

Especifica el tipo JSON de un valor. Los tipos válidos son "string", "number", "integer", "boolean", "array", "object" y "null". Puedes permitir varios tipos con un array:

{ "type": ["string", "null"] }  // el valor puede ser un string o null

properties

Define el esquema para cada clave de un objeto. Cada entrada es a su vez un esquema:

{
  "type": "object",
  "properties": {
    "firstName": { "type": "string" },
    "lastName":  { "type": "string" },
    "age":       { "type": "integer", "minimum": 0 }
  }
}

required

Un array de nombres de claves que deben estar presentes en el objeto. Una clave listada en properties pero no en required es opcional — puede faltar, pero si está presente debe cumplir con su esquema.

items

Define el esquema para cada elemento de un array. Este esquema requiere un array de cadenas:

{
  "type": "array",
  "items": { "type": "string" }
}

Restricciones de cadenas

{
  "type": "string",
  "minLength": 1,
  "maxLength": 100,
  "pattern": "^[a-zA-Z0-9_]+
quot; // patrón regex }

Restricciones numéricas

{
  "type": "number",
  "minimum": 0,
  "maximum": 1,
  "multipleOf": 0.01   // debe ser múltiplo de 0.01
}

enum

Restringe un valor a un conjunto fijo de valores permitidos:

{ "enum": ["pending", "active", "suspended", "deleted"] }

additionalProperties

Controla si se permiten claves no listadas en properties. Ponlo a false para rechazar cualquier clave inesperada — útil para contratos de API estrictos:

{ "additionalProperties": false }

Un ejemplo real de JSON Schema

Aquí tienes un esquema para un producto en una API de e-commerce — del tipo que verías en una definición OpenAPI o en un contrato de datos 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
}

Cómo validar JSON contra un esquema

¿Eligiendo un validador jsonschema? Las opciones estándar son Ajv (JavaScript), jsonschema (Python) y servicios online como jsonschemavalidator.net. Si necesitas la dirección contraria — generar json schema desde un ejemplo, o un json schema desde un documento json — prueba GenSON en Python o transform.tools en el navegador. Son herramientas json schema generator que infieren un esquema de partida a partir de una muestra. Después aprieta a mano required, additionalProperties y las restricciones de valor.

En JavaScript (Ajv)

Ajv es el validador de JSON Schema más usado en el ecosistema JavaScript. Soporta Draft-07 y Draft 2020-12.

npm install ajv
import 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) devuelve una función validate reutilizable. Compilar una vez y llamar al resultado repetidamente es bastante más rápido que recompilar en cada llamada.

En JavaScript (navegador, sin dependencias)

Para comprobaciones simples de tipo y de campos obligatorios sin añadir una dependencia, puedes validar manualmente — pero para cualquier cosa más allá de comprobaciones triviales, usa Ajv. La lógica de validación de esquemas es lo bastante compleja como para que hacerla a mano sea propenso a errores.

En Python (jsonschema)

pip install jsonschema
import 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 un archivo JSON contra un esquema

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)

En el navegador (fixjson)

Si necesitas comprobar que un documento JSON es estructuralmente válido antes de trabajar con él — sin escribir código — el validador JSON de fixjson comprueba la sintaxis y marca los errores al instante. Pega tu JSON y cualquier problema de sintaxis aparece inline con la línea y la posición exactas de cada error.

Para una validación completa de esquema (comprobar tipos, campos obligatorios, restricciones), usa uno de los enfoques basados en librerías de arriba, o una herramienta dedicada de prueba de esquemas como jsonschemavalidator.net.

$ref: reutilizar esquemas

Los esquemas reales no definen todo inline. La palabra clave $ref te permite referenciar otro esquema por su $id o por una ruta JSON Pointer dentro del mismo documento, manteniendo los esquemas DRY y componibles.

{
  "$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 es el lugar estándar para definir subesquemas reutilizables dentro de un único archivo (reemplazó a definitions en el Draft 2019-09).

Combinar esquemas: allOf, anyOf, oneOf

JSON Schema tiene tres palabras clave de composición para expresar «debe coincidir con todos», «debe coincidir con al menos uno» y «debe coincidir con exactamente uno»:

// allOf: debe satisfacer cada esquema listado
{
  "allOf": [
    { "type": "object" },
    { "required": ["id"] },
    { "properties": { "id": { "type": "integer" } } }
  ]
}

// anyOf: debe satisfacer al menos un esquema
{
  "anyOf": [
    { "type": "string" },
    { "type": "null" }
  ]
}

// oneOf: debe satisfacer exactamente un esquema (deben ser mutuamente excluyentes)
{
  "oneOf": [
    { "properties": { "type": { "const": "circle" } }, "required": ["radius"] },
    { "properties": { "type": { "const": "rectangle" } }, "required": ["width", "height"] }
  ]
}

La palabra clave format: date-time, email, uri, uuid

Más allá de los tipos crudos, la palabra clave format de JSON Schema anota cadenas con su forma esperada — un date-time ISO, una dirección de email, un URI, un UUID, una IP, etc. Se ve así:

{
  "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" }
  }
}

Un punto sutil pero importante: en Draft 2020-12 (y 2019-09), la palabra clave format es una anotación por defecto — no aplica el formato a menos que se configure el validador para hacerlo. En Draft-07 y anteriores, era aserción por defecto en algunos validadores. Para hacerlo estricto en Ajv:

import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);              // registra date-time, email, uri, uuid, etc.

// En 2020-12 hay que activar la aserción de format en tu meta-esquema o
// pasar { validateFormats: true } explícitamente, según la versión de Ajv.

Valores comunes de format: date-time, date, time, duration, email, idn-email, hostname, ipv4, ipv6, uri, uri-reference, uuid, regex, json-pointer.

Trata format como una pista, no como una frontera de seguridad — una cadena que pasa format: "email" sigue siendo input no confiable. Para entrega real o validez verdadera, verifica fuera de banda (DNS, enviar un email de confirmación, ejecutar una regex que controlas).

Errores comunes en JSON Schema

Confundir «properties» con «required»

Listar una clave bajo properties no la hace obligatoria. Una clave en properties define el esquema para esa clave si aparece. Para exigir su presencia, también debes listarla en required.

Usar «integer» cuando quieres decir «number»

"type": "integer" rechaza 3.14. Si tu campo puede ser cualquier número (incluidos decimales), usa "type": "number".

Olvidar que «additionalProperties» es true por defecto

Por defecto, JSON Schema permite cualquier propiedad adicional no listada en properties. Es intencional — los esquemas están pensados para ser abiertos por defecto, siguiendo la ley de Postel. Si quieres un objeto cerrado, pon explícitamente "additionalProperties": false.

No especificar $schema

Los distintos drafts tienen semánticas distintas. Omitir la palabra clave $schema deja a los validadores adivinando qué versión usar. Inclúyela siempre:

{ "$schema": "https://json-schema.org/draft/2020-12/schema" }

Tratar la validación de JSON Schema como validación de seguridad

JSON Schema valida estructura y tipos — no es una herramienta de sanitización. Una cadena que pasa "type": "string" todavía podría contener inyección SQL, payloads XSS u otro contenido malicioso. La validación de esquema es una primera barrera, no una medida de seguridad completa.

JSON Schema y OpenAPI

OpenAPI (antes Swagger) usa un subconjunto de JSON Schema para describir cuerpos de solicitud, cuerpos de respuesta y parámetros. Si has escrito una especificación OpenAPI, has escrito JSON Schema — aunque OpenAPI usa un dialecto modificado con algunas extensiones y restricciones.

Esto significa que el conocimiento de JSON Schema se transfiere directamente al diseño de APIs. La sección components/schemas de un documento OpenAPI es una colección de JSON Schemas, y herramientas como Stoplight, Redoc y Swagger UI las renderizan automáticamente como documentación interactiva.

Trabajar con Ajv en la práctica

Dos flags se amortizan solos en cualquier proyecto real:

  • strict: true (predeterminado en Ajv moderno) — rechaza palabras clave desconocidas y formatos desconocidos en tiempo de compilación de esquema, detectando typos como "minimun" o un $schema ausente antes de que dejen pasar datos en silencio.
  • allErrors: true — recolecta todos los fallos de validación en lugar de parar en el primero. Combina bien con ajv.errorsText() para mensajes orientados al usuario.

Para generar JSON falso a partir de un esquema para tests y fixtures, usa json-schema-faker: recorre el esquema y produce valores que encajan (tipos, rangos, enums, incluso format si lo combinas con ajv-formats). Útil para pruebas basadas en propiedades o para sembrar una UI desde un esquema.

Generar un JSON Schema a partir de JSON existente

Si tienes datos JSON y quieres generar un esquema de partida a partir de ellos, varias herramientas automatizan el proceso:

  • quicktype.io — infiere esquemas (y definiciones de tipos para TypeScript, Go, Python y más) a partir de JSON de muestra
  • generate-schema (npm) generate-schema json schema.json data.json
  • Python: gensonpip install genson, luego SchemaBuilder infiere un esquema a partir de uno o varios objetos de muestra

Los esquemas generados son un punto de partida, no un producto terminado. Infieren tipos a partir de datos de muestra, pero no conocen tus reglas de negocio — no pueden inferir que un campo string es un email, ni que un entero debe ser positivo, ni que dos campos son mutuamente excluyentes. Revisa y aprieta siempre un esquema generado antes de usarlo en producción.

Preguntas frecuentes

¿Para qué sirve JSON Schema?

Para describir y validar la estructura de datos JSON — qué claves son obligatorias, qué tipo debe tener cada valor y qué valores están permitidos. Está detrás de OpenAPI, el autocompletado en IDE para package.json/tsconfig.json, la generación de formularios y los contratos de pipelines de datos.

¿Cuál es la diferencia entre JSON y JSON Schema?

JSON son los datos; JSON Schema es un documento JSON aparte que describe cómo deben ser los datos válidos. Si te inicias en el propio formato, empieza por ¿Qué es JSON?.

¿Qué draft de JSON Schema debería usar?

Draft 2020-12 es el actual y el recomendado para esquemas nuevos; Draft-07 sigue siendo común por el amplio soporte de herramientas. Declara siempre la versión con $schema para que los validadores no adivinen.

¿Cómo valido JSON contra un esquema?

Usa Ajv en JavaScript, la librería jsonschema en Python (ejemplos arriba), o un validador web. Para confirmar primero que el JSON es sintácticamente válido, mira Cómo validar JSON o pásalo por el validador.

¿JSON Schema valida format (email, date-time, uri…)?

En Draft 2020-12 / 2019-09 la palabra clave format es una anotación por defecto — los validadores solo la aplican cuando se configuran para ello. Con Ajv, registra ajv-formats y activa la aserción de formato para rechazar valores mal formados de verdad.

Conclusión

JSON Schema convierte la documentación informal («este campo debería ser un número») en un contrato verificable por máquina que los validadores pueden hacer cumplir de forma coherente entre lenguajes, equipos y sistemas. El vocabulario central — type, properties, required, items, enum — cubre la gran mayoría de los casos reales. Funciones más avanzadas como $ref, palabras clave de composición y format cubren el resto.

Empieza con un esquema mínimo que solo imponga lo que realmente necesitas imponer. Añade restricciones de forma incremental a medida que tu comprensión de los datos se afianza. Un esquema que rechaza datos válidos es peor que no tener esquema.

Si el JSON que estás validando tiene errores de sintaxis incluso antes de llegar al validador de esquema, arréglalos primero — un validador de esquema requiere JSON sintácticamente correcto como entrada. Cuando el JSON esté limpio, valídalo y entonces aplica tu esquema.