Guida alla validazione JSON Schema: convalida le tue strutture dati
Ogni applicazione che riceve dati da fonti esterne affronta lo stesso problema fondamentale: posso fidarmi di questi dati? Che si tratti di corpi di richieste API, file di configurazione, messaggi in coda o importazioni di dati, i dati non attendibili devono essere convalidati prima di entrare nel sistema. JSON Schema fornisce un modo standardizzato e indipendente dal linguaggio per definire l'aspetto dei dati validi e convalidare i dati in entrata rispetto a quella definizione. Questa guida copre tutto, dalla scrittura del primo Schema ai pattern avanzati per validazioni complesse, con esempi pratici che puoi applicare immediatamente.
Cos'è JSON Schema?
JSON Schema è un documento JSON che descrive la struttura e i vincoli di altri documenti JSON. È un vocabolario che ti consente di annotare e convalidare dati JSON, standardizzato dall'Internet Engineering Task Force (IETF). JSON Schema definisce regole su quali campi devono esistere, di che tipo devono essere, quali valori sono accettabili e come dovrebbero essere strutturati oggetti e array.
Pensa a JSON Schema come al contratto dei tuoi dati. Proprio come uno schema di database definisce le colonne, i tipi e i vincoli delle tabelle, JSON Schema definisce le proprietà, i tipi e i vincoli dei documenti JSON. Qualsiasi dato JSON che soddisfa tutti i vincoli nello Schema è chiamato istanza valida, mentre i dati che violano qualsiasi vincolo sono non validi.
Cosa non è JSON Schema
- Non è un formato di dati: JSON Schema non definisce come i dati vengono serializzati o trasmessi. Descrive solo l'aspetto dei dati validi.
- Non è un sostituto della logica di business: la validazione Schema controlla la correttezza strutturale (tipi, formati, intervalli). Le regole di business complesse (come "un utente non può trasferire più del suo saldo") appartengono al codice dell'applicazione.
- Non è uno schema di database: sebbene concettualmente simili, JSON Schema valida documenti JSON, non tabelle di database. Tuttavia, puoi utilizzare JSON Schema insieme ai vincoli del database per una difesa in profondità.
Versioni di JSON Schema
JSON Schema si è evoluto attraverso diverse bozze, ognuna delle quali ha aggiunto funzionalità e perfezionato il vocabolario. Comprendere le versioni ti aiuta a scegliere quella giusta per il tuo progetto ed evitare problemi di compatibilità.
| Versione | URI $schema | Stato | Funzionalità principali |
|---|---|---|---|
| Draft 2020-12 | https://json-schema.org/draft/2020-12/schema | Versione corrente | prefixItems, dynamicRef, supporto vocabolario |
| Draft 2019-09 | https://json-schema.org/draft/2019-09/schema | Stabile | unevaluatedProperties, $recursiveRef |
| Draft 7 | http://json-schema.org/draft-07/schema# | Ampiamente supportato | if/then/else, contentEncoding |
| Draft 6 | http://json-schema.org/draft-06/schema# | Legacy | propertyNames, contains |
| Draft 4 | http://json-schema.org/draft-04/schema# | Deprecato | Prima versione ampiamente adottata |
Scrivere il tuo primo Schema
Cominciamo con un semplice esempio: uno Schema per un oggetto utente con nome, email ed età.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json",
"title": "User",
"description": "A user account in the system",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "The user's full name"
},
"email": {
"type": "string",
"format": "email",
"description": "The user's email address"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150,
"description": "The user's age in years"
}
},
"required": ["name", "email"],
"additionalProperties": false
}Questo Schema dichiara che un utente valido deve essere un oggetto con name e email come proprietà stringa obbligatorie. La proprietà age è opzionale ma se presente deve essere un intero tra 0 e 150. Il vincolo additionalProperties: false impedisce qualsiasi proprietà non definita nello Schema, il che può catturare errori di battitura e campi imprevisti.
Riferimento alle parole chiave principali
JSON Schema fornisce un ricco vocabolario di parole chiave per definire i vincoli. Ecco le parole chiave più importanti, organizzate per categoria.
Parola chiave type
| Parola chiave | Descrizione | Esempio |
|---|---|---|
| type | Tipo di dato previsto | "type": "string" o "type": ["string", "null"] |
| enum | Elenco di valori consentiti | "enum": ["active", "inactive", "pending"] |
| const | Deve essere uguale a questo valore esatto | "const": "v2" |
Vincoli numerici
| Parola chiave | Descrizione | Esempio |
|---|---|---|
| minimum | Valore minimo (incluso) | "minimum": 0 |
| exclusiveMinimum | Valore minimo (escluso) | "exclusiveMinimum": 0 |
| maximum | Valore massimo (incluso) | "maximum": 100 |
| exclusiveMaximum | Valore massimo (escluso) | "exclusiveMaximum": 100 |
| multipleOf | Deve essere un multiplo di questo valore | "multipleOf": 0.01 |
Vincoli sulle stringhe
| Parola chiave | Descrizione | Esempio |
|---|---|---|
| minLength | Lunghezza minima della stringa | "minLength": 1 |
| maxLength | Lunghezza massima della stringa | "maxLength": 255 |
| pattern | Espressione regolare a cui la stringa deve corrispondere | "pattern": "^[A-Z]{2}\\d{4}$" |
| format | Formato semantico (email, uri, date-time, ecc.) | "format": "email" |
Vincoli sugli oggetti
| Parola chiave | Descrizione | Esempio |
|---|---|---|
| properties | Schema per ogni proprietà conosciuta | "properties": {"name": {"type": "string"}} |
| required | Elenco delle proprietà obbligatorie | "required": ["name", "email"] |
| additionalProperties | Se sono consentite proprietà aggiuntive | "additionalProperties": false |
| minProperties | Numero minimo di proprietà | "minProperties": 1 |
| maxProperties | Numero massimo di proprietà | "maxProperties": 10 |
| patternProperties | Schema per proprietà che corrispondono a una regex | "patternProperties": {"^S_": {"type": "string"}} |
Vincoli sugli array
| Parola chiave | Descrizione | Esempio |
|---|---|---|
| items | Schema per tutti gli elementi dell'array | "items": {"type": "string"} |
| prefixItems | Schema per elementi posizionali (Draft 2020-12) | "prefixItems": [{"type": "string"}, {"type": "number"}] |
| minItems | Numero minimo di elementi | "minItems": 1 |
| maxItems | Numero massimo di elementi | "maxItems": 100 |
| uniqueItems | Tutti gli elementi devono essere unici | "uniqueItems": true |
Pattern comuni di Schema
Gli Schema del mondo reale spesso richiedono pattern che vanno oltre il semplice controllo dei tipi. Ecco i pattern più comunemente utilizzati.
Validazione condizionale con if/then/else
Usa la logica condizionale per applicare vincoli diversi in base ai valori delle proprietà. Ad esempio, un oggetto pagamento richiede campi diversi a seconda del metodo di pagamento.
{
"type": "object",
"properties": {
"method": { "enum": ["credit_card", "bank_transfer"] },
"card_number": { "type": "string" },
"routing_number": { "type": "string" }
},
"required": ["method"],
"if": {
"properties": { "method": { "const": "credit_card" } }
},
"then": {
"required": ["card_number"]
},
"else": {
"required": ["routing_number"]
}
}Combinazione con allOf, anyOf, oneOf
Le parole chiave di composizione ti consentono di combinare Schema in modi potenti:
- allOf: i dati devono soddisfare tutti i sotto-Schema. Usato per combinare vincoli multipli o incorporare frammenti di Schema riutilizzabili.
- anyOf: i dati devono soddisfare almeno un sotto-Schema. Usato per tipi unione dove più forme sono accettabili.
- oneOf: i dati devono soddisfare esattamente un sotto-Schema. Usato per alternative mutuamente esclusive.
{
"oneOf": [
{
"type": "object",
"properties": {
"type": { "const": "email" },
"address": { "type": "string", "format": "email" }
},
"required": ["type", "address"]
},
{
"type": "object",
"properties": {
"type": { "const": "phone" },
"number": { "type": "string", "pattern": "^\\+?[1-9]\\d{1,14}$" }
},
"required": ["type", "number"]
}
]
}Riutilizzo di Schema con $ref
La parola chiave $ref ti consente di fare riferimento e riutilizzare Schema, eliminando la duplicazione e mantenendo gli Schema manutenibili. Puoi fare riferimento a Schema all'interno dello stesso documento o in file esterni.
{
"$id": "https://example.com/schemas/order.json",
"type": "object",
"properties": {
"customer": { "$ref": "#/$defs/address" },
"shipping": { "$ref": "#/$defs/address" },
"billing": { "$ref": "#/$defs/address" },
"items": {
"type": "array",
"items": { "$ref": "#/$defs/lineItem" },
"minItems": 1
}
},
"required": ["customer", "items"],
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zip": { "type": "string", "pattern": "^\\d{5}(-\\d{4})?$" },
"country": { "type": "string", "minLength": 2, "maxLength": 2 }
},
"required": ["street", "city", "zip", "country"]
},
"lineItem": {
"type": "object",
"properties": {
"product": { "type": "string" },
"quantity": { "type": "integer", "minimum": 1 },
"price": { "type": "number", "exclusiveMinimum": 0 }
},
"required": ["product", "quantity", "price"]
}
}
}Tipi nullable
In JSON Schema Draft 2020-12, i tipi nullable sono rappresentati utilizzando un array di tipi che include "null":
{
"type": ["string", "null"],
"description": "An optional display name, or null if not set"
}Nelle bozze precedenti, la specifica OpenAPI utilizzava la parola chiave nullable: true. Per JSON Schema standard, usa sempre l'approccio con array di tipi.
Validazione del formato
La parola chiave format fornisce una validazione semantica oltre il controllo strutturale. Specifica che una stringa deve essere conforme a un formato ben noto. I formati comunemente supportati includono:
| Formato | Descrizione | Esempio |
|---|---|---|
| Indirizzo email | user@example.com | |
| uri | URI valido | https://example.com/path |
| uri-reference | URI o riferimento relativo | /path/to/resource |
| date-time | Data e ora ISO 8601 | 2026-05-19T14:30:00Z |
| date | Data ISO 8601 | 2026-05-19 |
| time | Ora ISO 8601 | 14:30:00Z |
| ipv4 | Indirizzo IPv4 | 192.168.1.1 |
| ipv6 | Indirizzo IPv6 | ::1 |
| uuid | Identificatore univoco universale | 550e8400-e29b-41d4-a716-446655440000 |
| hostname | Nome host Internet | www.example.com |
Validare dati JSON a livello di codice
La validazione Schema è più utile quando integrata nel codice dell'applicazione. Ecco esempi che utilizzano librerie popolari in diversi linguaggi.
JavaScript con Ajv
Ajv è il validatore JSON Schema più utilizzato in JavaScript. Supporta tutte le versioni delle bozze e offre prestazioni eccellenti grazie alla compilazione JIT degli Schema.
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv);
const schema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'email'],
additionalProperties: false
};
const validate = ajv.compile(schema);
const valid = validate({ name: 'Alice', email: 'alice@example.com', age: 30 });
if (!valid) {
console.log(validate.errors);
// [{ keyword: 'required', params: { missingProperty: 'email' }, ... }]
}Python con jsonschema
from jsonschema import validate, ValidationError
schema = {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"email": {"type": "string", "format": "email"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name", "email"],
"additionalProperties": False
}
try:
validate(instance={"name": "Alice", "email": "alice@example.com"}, schema=schema)
except ValidationError as e:
print(f"Validation failed: {e.message}")Validazione dati API con JSON Schema
Una delle applicazioni più preziose di JSON Schema è la validazione dei dati di richiesta e risposta delle API. Questo garantisce che la tua API riceva input ben formati e restituisca dati nel formato previsto, catturando gli errori precocemente e fornendo messaggi di errore chiari ai client.
Middleware Express.js
import Ajv from 'ajv';
const ajv = new Ajv({ allErrors: true });
function validateBody(schema) {
const validate = ajv.compile(schema);
return (req, res, next) => {
if (!validate(req.body)) {
return res.status(400).json({
error: 'Validation failed',
details: validate.errors
});
}
next();
};
}
app.post('/api/users',
validateBody({
type: 'object',
properties: {
name: { type: 'string', minLength: 1, maxLength: 100 },
email: { type: 'string', format: 'email' },
role: { enum: ['admin', 'editor', 'viewer'] }
},
required: ['name', 'email'],
additionalProperties: false
}),
(req, res) => {
// req.body is guaranteed valid here
createUser(req.body);
}
);OpenAPI e JSON Schema
OpenAPI (precedentemente Swagger) utilizza un sottoinsieme di JSON Schema per definire gli Schema di richiesta e risposta delle API. Se stai già utilizzando OpenAPI, puoi estrarre gli Schema dalla specifica API e utilizzarli per la validazione a runtime. Strumenti come openapi-schema-validator e express-openapi-validator possono automatizzare questo processo, garantendo che la documentazione API e la logica di validazione rimangano sempre sincronizzate.
Migliori pratiche
- Imposta sempre $schema: includi la parola chiave $schema per dichiarare quale versione della bozza utilizza il tuo Schema. Questo previene ambiguità e garantisce che i validatori interpretino correttamente il tuo Schema.
- Usa $id per l'identificazione dello Schema: la parola chiave $id fornisce un identificatore univoco per il tuo Schema e funge da URI di base per la risoluzione dei riferimenti $ref. Impostala sempre, anche per Schema locali.
- Imposta additionalProperties: false: per impostazione predefinita, JSON Schema consente qualsiasi proprietà aggiuntiva negli oggetti. Impostare additionalProperties: false cattura errori di battitura e campi imprevisti, rendendo lo Schema più rigoroso e l'API più prevedibile.
- Usa $defs per componenti riutilizzabili: definisci Schema comuni in $defs e fai riferimento ad essi con $ref. Questo riduce la duplicazione e rende gli Schema più manutenibili.
- Aggiungi descrizioni: ogni proprietà e Schema dovrebbe avere un campo description. Questo serve sia come documentazione che per aiutare altri sviluppatori a comprendere lo scopo e i vincoli di ogni campo.
- Convalida ai confini del sistema: applica la validazione Schema ai bordi del tuo sistema: endpoint API, consumer di messaggi, pipeline di importazione dati e caricatori di configurazione. Non convalidare dati che il tuo stesso codice ha già prodotto e di cui ti fidi.
- Abilita la modalità strict nei validatori: configura il validatore per rifiutare parole chiave sconosciute, applicare la validazione del formato e riportare tutti gli errori invece di fermarsi al primo errore. Questo cattura più problemi in un unico passaggio di validazione.
- Versiona i tuoi Schema: includi la versione dello Schema nell'URI $id (ad esempio https://example.com/schemas/user/v2.json). Questo ti consente di far evolvere gli Schema senza rompere i consumer esistenti.
- Testa i tuoi Schema: scrivi test unitari per i tuoi Schema con esempi validi e non validi. Questo garantisce che il tuo Schema applichi i vincoli che intendi e cattura le regressioni quando lo Schema viene modificato.
- Usa format per la validazione semantica: preferisci format: "email" invece di pattern regex complessi. I formati sono più leggibili, più manutenibili e beneficiano della logica di validazione ben testata nelle librerie dei validatori.
Hai bisogno di validare dati JSON rispetto a uno Schema? Prova il nostro validatore JSON Schema online gratuito. Incolla il tuo Schema e i tuoi dati per ottenere risultati di validazione istantanei con messaggi di errore dettagliati.
Validatore JSON SchemaStrumento di formattazione JSONDomande frequenti
Cos'è JSON Schema?
JSON Schema è un documento JSON che descrive la struttura e i vincoli di altri documenti JSON. Ti consente di definire campi obbligatori, tipi di dati previsti, intervalli di valori, pattern di stringhe e strutture di oggetti annidati. Puoi usarlo per convalidare dati in entrata, generare documentazione e creare automaticamente interfacce di moduli.
Quale versione di JSON Schema dovrei usare?
Usa JSON Schema Draft 2020-12 per i nuovi progetti. È l'ultima versione stabile, supportata dai principali validatori come Ajv. Se hai bisogno di compatibilità con strumenti più vecchi, Draft 7 è anch'esso ampiamente supportato. Evita Draft 4 e versioni precedenti, poiché utilizzano parole chiave obsolete e mancano di funzionalità moderne.
Qual è la differenza tra JSON Schema e le interfacce TypeScript?
Le interfacce TypeScript forniscono solo controllo dei tipi a tempo di compilazione nel codice TypeScript. JSON Schema fornisce validazione a runtime attraverso i linguaggi di programmazione, e può convalidare dati da qualsiasi fonte (richieste API, file, database). Usa TypeScript per la sicurezza in fase di sviluppo e JSON Schema per la validazione dei dati a runtime ai confini del sistema.
JSON Schema può validare i corpi delle richieste API?
Sì, JSON Schema è ampiamente utilizzato per la validazione di richieste e risposte API. Framework come Express (con express-json-validator), FastAPI e Spring Boot supportano la validazione JSON Schema nativamente o tramite middleware. La validazione dei corpi delle richieste rispetto a uno Schema garantisce che i dati in entrata abbiano la struttura corretta prima che l'applicazione li elabori.
Quali sono le parole chiave JSON Schema più importanti?
Le parole chiave più critiche sono: type (tipo di dato), properties (campi oggetto), required (campi obbligatori), items (Schema degli elementi array), minimum/maximum (limiti numerici), minLength/maxLength (limiti di stringa), pattern (regex per stringhe), enum (valori consentiti) e $ref (riferimenti per riutilizzare Schema). Queste parole chiave coprono la stragrande maggioranza delle esigenze di validazione.