Generador de JSON Schema
Genera un esquema draft 2020-12 a partir de un ejemplo, con campos obligatorios honestos.
Nada de lo que pegues sale de tu navegador. La lista de permitidos de connect-src convierte eso en una garantía del navegador, no en una promesa. Compruébalo tú mismo
Genera un JSON Schema a partir de un payload de ejemplo. Draft 2020-12 por defecto, con 2019-09 y draft-07 disponibles.
Generar un esquema a partir de una sola muestra es inferencia, y la inferencia es donde estas herramientas mienten en voz baja. Cada suposición que hace esta se te reporta, y la más grande se trata de forma distinta a como lo hacen la mayoría de generadores.
El problema de los campos obligatorios
La mayoría de generadores leen el primer elemento de un array y toman sus claves como la forma. Eso produce un esquema que rechaza datos válidos en cuanto un registro posterior tiene un campo opcional que al primero le faltaba.
Este generador fusiona todos los elementos. Una clave presente en todos entra en required; una clave presente en algunos aparece en properties pero no en required. Esa única diferencia es la razón para usar un generador en vez de escribir el esquema a mano tras echarle un vistazo al payload.
Las demás inferencias, todas reportadas
- integer frente a number
- Un campo solo se tipa como integer cuando todos los valores observados lo eran. Un solo decimal en cualquier parte convierte el campo entero en number.
- Campos anulables
- Un campo visto como cadena y como null pasa a ser "type": ["string", "null"], y no un campo descartado ni simplemente "string".
- format
- Se emite solo cuando todos los valores observados encajan: date-time, date, time, email, uuid, ipv4 o uri. Un solo valor que no encaje y la anotación desaparece.
- enum
- Se sugiere en vez de darse por hecho, y solo cuando se repite un conjunto pequeño de valores. Desactivado por defecto, porque un enum inferido de una muestra es una suposición sobre un dominio que no has visto entero.
- Enteros inseguros
- Se tipan como integer y se reportan, porque un validador que corra sobre un parser de JavaScript ya ha perdido el valor antes de empezar a validar.
La palabra clave format no valida
Esto sorprende a la gente y despliega validaciones rotas. En draft 2019-09 y draft 2020-12, format es por defecto una ANOTACIÓN y no una aserción. La mayoría de validadores aceptarán tan tranquilos "no-es-un-email" para un campo marcado con "format": "email", salvo que actives explícitamente la aserción de format.
Si necesitas que se aplique, añade un pattern explícito junto al format, o configura tu validador para el comportamiento de aserción y comprueba que tu validador lo soporta.
Una advertencia sobre validar el resultado
Si llevas este esquema a Ajv, el validador de JavaScript más habitual, presta atención al punto de entrada. La exportación ajv por defecto solo soporta draft-07. Draft 2020-12 necesita ajv/dist/2020 y 2019-09 necesita ajv/dist/2019.
Si te equivocas ahí, un esquema 2020-12 que use prefixItems se valida con la semántica de draft-07, donde prefixItems es una palabra clave desconocida y se ignora. Tu validador entonces reporta «válido» sobre datos que no lo son. Eso es peor que un error, y es fácil hacerlo sin querer.
How to do this in code
Generar y validar en código.
js JavaScript, Ajv
import Ajv from "ajv" te da un validador draft-07, que ignora en silencio las palabras clave de 2020-12.
// The entry point matters. This is the 2020-12 one.
import Ajv2020 from 'ajv/dist/2020';
import addFormats from 'ajv-formats';
const ajv = new Ajv2020({ allErrors: true });
addFormats(ajv); // without this, "format" does nothing at all
const validate = ajv.compile(schema);
if (!validate(data)) console.error(validate.errors); py Python
from jsonschema import Draft202012Validator
validator = Draft202012Validator(schema)
for error in sorted(validator.iter_errors(data), key=lambda e: e.path):
print(list(error.path), error.message)
# Format checking is opt-in here too
from jsonschema import FormatChecker
Draft202012Validator(schema, format_checker=FormatChecker()).validate(data) go Go
import "github.com/santhosh-tekuri/jsonschema/v6"
c := jsonschema.NewCompiler()
sch, err := c.Compile("schema.json")
if err := sch.Validate(data); err != nil {
fmt.Println(err)
} Preguntas frecuentes
- ¿Qué draft debería usar?
- Draft 2020-12 para cualquier cosa nueva; es el draft publicado actual y con el que se alinea OpenAPI 3.1. draft-07 sigue siendo el más soportado en herramientas antiguas. Ten en cuenta que el identificador 2020-12 se refiere a cuándo se cerró el draft: los documentos en esa URI se republicaron por última vez en junio de 2022, lo cual es un parche y no una versión nueva.
- ¿Por qué falta un campo en required?
- Porque estaba ausente en al menos una muestra. Eso es el generador diciéndote algo útil. Si el campo es de verdad obligatorio, dale una muestra donde todos los registros lo tengan, o añádelo a required a mano.
- ¿Puede generar a partir de varias muestras?
- Sí, y deberías. Mete tus muestras en un array y pega el array. Fusionar a lo largo de muchos registros es exactamente lo que hace que required y la anulabilidad sean precisos.