Vai al contenuto
jsonbeautifiers
Italiano

Generatore di JSON Schema

Genera uno schema draft 2020-12 da un campione, con campi obbligatori onesti.

JSON di esempio
Schema

Nulla di ciò che incolli lascia il tuo browser. L’allowlist connect-src ne fa una garanzia del browser anziché una promessa. Verificalo tu stesso

Genera un JSON Schema da un payload di esempio. Draft 2020-12 per impostazione predefinita, con 2019-09 e draft-07 disponibili.

Generare uno schema da un solo campione è inferenza, e l’inferenza è il punto in cui questi strumenti mentono sottovoce. Ogni supposizione fatta qui ti viene riportata, e quella più importante è trattata diversamente rispetto alla maggior parte dei generatori.

Il problema dei campi obbligatori

Quasi tutti i generatori leggono il primo elemento di un array e prendono le sue chiavi come forma. Ne esce uno schema che rifiuta dati validi nel momento in cui un record successivo ha un campo opzionale che al primo mancava.

Questo generatore unisce tutti gli elementi. Una chiave presente in tutti finisce in required; una chiave presente solo in alcuni compare in properties ma non in required. Quell’unica differenza è il motivo per usare un generatore invece di scrivere lo schema a mano dopo un’occhiata al payload.

Le altre inferenze, tutte segnalate

integer contro number
Un campo viene tipizzato integer solo quando ogni valore osservato lo era. Un singolo decimale da qualche parte rende number l’intero campo.
Campi nullable
Un campo visto sia come stringa sia come null diventa "type": ["string", "null"], non un campo eliminato né un semplice "string".
format
Emesso solo quando ogni valore osservato corrisponde: date-time, date, time, email, uuid, ipv4 o uri. Basta un valore che non corrisponde e l’annotazione salta.
enum
Suggerito anziché dato per scontato, e solo quando un piccolo insieme di valori si ripete. Disattivato di default, perché un enum dedotto da un campione è un’ipotesi su un dominio che non hai visto per intero.
Interi non sicuri
Tipizzati integer e segnalati, perché un validatore che gira su un parser JavaScript ha già perso il valore prima ancora di iniziare a validare.

La parola chiave format non valida

Questa cosa sorprende e manda in produzione validazioni rotte. Nei draft 2019-09 e 2020-12, format è per impostazione predefinita un’ANNOTAZIONE e non un’asserzione. La maggior parte dei validatori accetterà tranquillamente "non-una-email" per un campo marcato "format": "email", a meno che l’asserzione su format non sia attivata esplicitamente.

Se ti serve che venga applicata, aggiungi un pattern esplicito accanto al format, oppure configura il validatore per il comportamento ad asserzione e verifica che lo supporti.

Un avvertimento sul validare il risultato

Se porti questo schema in Ajv, il validatore JavaScript più diffuso, attenzione al punto di ingresso. L’export ajv predefinito supporta solo draft-07. Il draft 2020-12 richiede ajv/dist/2020 e il 2019-09 richiede ajv/dist/2019.

Sbagliare qui significa che uno schema 2020-12 che usa prefixItems viene validato con la semantica del draft-07, dove prefixItems è una parola chiave sconosciuta e viene ignorata. Il tuo validatore riporta allora «valido» su dati che non lo sono. È peggio di un errore, ed è facile farlo per sbaglio.

How to do this in code

Generare e validare nel codice.

js JavaScript, Ajv

import Ajv from "ajv" ti dà un validatore draft-07, che ignora in silenzio le parole chiave del 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)
}

Domande frequenti

Quale draft conviene usare?
Draft 2020-12 per tutto ciò che è nuovo; è il draft pubblicato corrente ed è quello a cui si allinea OpenAPI 3.1. Il draft-07 resta il più supportato dagli strumenti più vecchi. Nota che l’identificatore 2020-12 si riferisce a quando il draft è stato chiuso: i documenti a quell’URI sono stati ripubblicati l’ultima volta a giugno 2022, il che è una correzione e non una nuova versione.
Perché manca un campo in required?
Perché era assente in almeno un campione. È il generatore che ti sta dicendo qualcosa di utile. Se il campo è davvero obbligatorio, dagli un campione in cui ogni record ce l’ha, oppure aggiungilo a required a mano.
Può generare da più campioni?
Sì, ed è quello che dovresti fare. Metti i campioni in un array e incolla l’array. Unire su molti record è esattamente ciò che rende accurati required e la nullabilità.