JSON Schema è un vocabolario per descrivere la struttura, i vincoli e i tipi di un documento JSON. Ti permette di definire esattamente come deve essere un JSON valido — quali chiavi sono obbligatorie, di che tipo deve essere ciascun valore, quali valori sono ammessi — e poi di validare automaticamente qualunque documento JSON rispetto a quelle regole. Questa guida spiega cos'è JSON Schema, come scriverne uno e come usarlo per validare JSON in JavaScript, Python e nel browser.
Cos'è JSON Schema?
JSON Schema è esso stesso un documento JSON. Descrive un altro documento JSON nello stesso modo in cui uno schema di database descrive una tabella: dichiara la forma attesa, i tipi e i vincoli dei dati. Un JSON Schema dice ai validatori — librerie, API, generatori di form, IDE — cosa significa «valido» per un certo pezzo di JSON.
La specifica è mantenuta su json-schema.org ed è attualmente al Draft 2020-12. È usata da OpenAPI (lo standard per documentare API REST), JSON Forms (generazione di UI da schema), tooling degli IDE (VS Code usa JSON Schema per alimentare l'autocomplete di package.json e tsconfig.json) e innumerevoli pipeline dati interne.
Un esempio minimo di JSON Schema
Ecco un documento JSON che rappresenta un utente, seguito da uno schema che ne descrive la struttura attesa:
// Il documento JSON da validare
{
"id": 42,
"name": "Alice",
"email": "alice@example.com",
"age": 30,
"active": true
}// Il 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
}Questo schema dice: il documento deve essere un oggetto; id, name ed email sono obbligatori; age, se presente, deve essere compreso tra 0 e 150; e non sono ammesse chiavi diverse dalle cinque elencate.
Le parole chiave principali
type
Specifica il tipo JSON di un valore. I tipi validi sono "string", "number", "integer", "boolean", "array", "object" e "null". Puoi permettere più tipi con un array:
{ "type": ["string", "null"] } // il valore può essere una stringa o nullproperties
Definisce lo schema per ogni chiave di un oggetto. Ogni voce è a sua volta uno schema:
{
"type": "object",
"properties": {
"firstName": { "type": "string" },
"lastName": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
}
}required
Un array di nomi di chiavi che devono essere presenti nell'oggetto. Una chiave elencata sotto properties ma non in required è opzionale — può mancare, ma se è presente deve rispettare il suo schema.
items
Definisce lo schema per ogni elemento di un array. Questo schema richiede un array di stringhe:
{
"type": "array",
"items": { "type": "string" }
}Vincoli sulle stringhe
{
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[a-zA-Z0-9_]+quot; // pattern regex
}Vincoli numerici
{
"type": "number",
"minimum": 0,
"maximum": 1,
"multipleOf": 0.01 // deve essere multiplo di 0.01
}enum
Limita un valore a un insieme fisso di valori ammessi:
{ "enum": ["pending", "active", "suspended", "deleted"] }additionalProperties
Controlla se sono ammesse chiavi non elencate in properties. Imposta a false per rifiutare qualunque chiave inattesa — utile per contratti API rigorosi:
{ "additionalProperties": false }Un esempio reale di JSON Schema
Ecco uno schema per un prodotto in un'API e-commerce — del tipo che vedresti in una definizione OpenAPI o in un contratto dati 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
}Come validare JSON rispetto a uno schema
Stai scegliendo un validatore jsonschema? Le scelte standard sono Ajv (JavaScript), jsonschema (Python) e servizi online come jsonschemavalidator.net. Se ti serve la direzione opposta — generare json schema da un esempio, o un json schema da un documento json — prova GenSON in Python o transform.tools nel browser. Sono strumenti json schema generator che inferiscono uno schema di partenza da un campione. Dopo, stringi a mano required, additionalProperties e i vincoli sui valori.
In JavaScript (Ajv)
Ajv è il validatore JSON Schema più diffuso nell'ecosistema JavaScript. Supporta Draft-07 e Draft 2020-12.
npm install ajvimport 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) restituisce una funzione validate riutilizzabile. Compilare una volta e chiamare il risultato ripetutamente è molto più veloce che ricompilare a ogni chiamata.
In JavaScript (browser, senza dipendenze)
Per semplici controlli di tipo e di campi obbligatori senza aggiungere una dipendenza, puoi validare a mano — ma per qualunque cosa oltre i controlli banali, usa Ajv. La logica di validazione degli schema è abbastanza complessa da rendere la scrittura a mano soggetta a errori.
In Python (jsonschema)
pip install jsonschemaimport 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}")Validare un file JSON rispetto a uno schema
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)Nel browser (fixjson)
Se devi controllare che un documento JSON sia strutturalmente valido prima di usarlo — senza scrivere codice — il validatore JSON di fixjson controlla la sintassi e segnala gli errori all'istante. Incolla il tuo JSON e ogni problema di sintassi compare inline con la riga e la posizione esatte di ciascun errore.
Per una validazione completa dello schema (controllo di tipi, campi obbligatori, vincoli), usa uno degli approcci basati su librerie qui sopra, o uno strumento di test schema dedicato come jsonschemavalidator.net.
$ref: riutilizzare schemi
Gli schemi reali non definiscono tutto inline. La parola chiave $ref permette di referenziare un altro schema tramite il suo $id o tramite un percorso JSON Pointer nello stesso documento, mantenendo gli schemi DRY e componibili.
{
"$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 è il posto standard per definire sub-schemi riutilizzabili all'interno di un singolo file (ha sostituito definitions nel Draft 2019-09).
Combinare schemi: allOf, anyOf, oneOf
JSON Schema ha tre parole chiave di composizione per esprimere «deve corrispondere a tutti», «deve corrispondere ad almeno uno» e «deve corrispondere a esattamente uno»:
// allOf: deve soddisfare ogni schema elencato
{
"allOf": [
{ "type": "object" },
{ "required": ["id"] },
{ "properties": { "id": { "type": "integer" } } }
]
}
// anyOf: deve soddisfare almeno uno schema
{
"anyOf": [
{ "type": "string" },
{ "type": "null" }
]
}
// oneOf: deve soddisfare esattamente uno schema (devono essere mutuamente esclusivi)
{
"oneOf": [
{ "properties": { "type": { "const": "circle" } }, "required": ["radius"] },
{ "properties": { "type": { "const": "rectangle" } }, "required": ["width", "height"] }
]
}La parola chiave format: date-time, email, uri, uuid
Oltre ai tipi grezzi, la parola chiave format di JSON Schema annota le stringhe con la loro forma attesa — un date-time ISO, un indirizzo email, un URI, un UUID, un indirizzo IP, e così via. Ha questo aspetto:
{
"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 sottile ma importante: nel Draft 2020-12 (e 2019-09), la parola chiave format è annotazione per impostazione predefinita — non impone il formato a meno che il validatore non sia configurato per farlo. Nel Draft-07 e precedenti, in alcuni validatori era assertion di default. Per renderlo stretto in Ajv:
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv();
addFormats(ajv); // registra date-time, email, uri, uuid, ecc.
// In 2020-12 devi abilitare la format assertion nel tuo meta-schema o
// passare esplicitamente { validateFormats: true }, a seconda della versione di Ajv.Valori format comuni: date-time, date, time, duration, email, idn-email, hostname, ipv4, ipv6, uri, uri-reference, uuid, regex, json-pointer.
Tratta format come un suggerimento, non come un confine di sicurezza — una stringa che passa format: "email" resta un input non fidato. Per la deliverability o per una validità reale, verifica fuori banda (DNS, invio di un'email di conferma, esecuzione di una regex che controlli tu).
Errori comuni in JSON Schema
Confondere «properties» con «required»
Elencare una chiave sotto properties non la rende obbligatoria. Una chiave in properties definisce lo schema di quella chiave se compare. Per imporne la presenza, devi elencarla anche in required.
Usare «integer» quando intendi «number»
"type": "integer" rifiuta 3.14. Se il tuo campo può essere un qualunque numero (decimali inclusi), usa "type": "number".
Dimenticare che «additionalProperties» è true di default
Di default, JSON Schema permette qualsiasi proprietà aggiuntiva non elencata sotto properties. È intenzionale — gli schemi sono pensati per essere aperti di default, seguendo la legge di Postel. Se vuoi un oggetto chiuso, imposta esplicitamente "additionalProperties": false.
Non specificare $schema
Draft diversi hanno semantiche diverse. Omettere la parola chiave $schema lascia i validatori a indovinare quale versione usare. Includila sempre:
{ "$schema": "https://json-schema.org/draft/2020-12/schema" }Considerare la validazione JSON Schema come validazione di sicurezza
JSON Schema valida struttura e tipi — non è uno strumento di sanitizzazione. Una stringa che passa "type": "string" potrebbe comunque contenere SQL injection, payload XSS o altro contenuto malevolo. La validazione di schema è una prima barriera, non una misura di sicurezza completa.
JSON Schema e OpenAPI
OpenAPI (ex Swagger) usa un sottoinsieme di JSON Schema per descrivere corpi di richiesta, corpi di risposta e parametri. Se hai scritto una specifica OpenAPI, hai scritto JSON Schema — anche se OpenAPI usa un dialetto modificato con alcune estensioni e restrizioni.
Questo significa che la conoscenza di JSON Schema si trasferisce direttamente al design delle API. La sezione components/schemas di un documento OpenAPI è una raccolta di JSON Schema, e strumenti come Stoplight, Redoc e Swagger UI li trasformano automaticamente in documentazione interattiva.
Lavorare con Ajv nella pratica
Due flag si ripagano da sole in qualunque progetto vero:
strict: true(default in Ajv moderno) — rifiuta parole chiave sconosciute e format sconosciuti in fase di compilazione dello schema, intercettando refusi come"minimun"o un$schemamancante prima che lascino passare i dati in silenzio.allErrors: true— raccoglie ogni fallimento di validazione invece di fermarsi al primo. Si combina bene conajv.errorsText()per messaggi rivolti all'utente.
Per generare JSON finto da uno schema per test e fixture, usa json-schema-faker: percorre lo schema e produce valori che combaciano (tipi, intervalli, enum e perfino format quando accoppiato con ajv-formats). Utile per test property-based o per seminare una UI da uno schema.
Generare un JSON Schema da JSON esistente
Se hai dei dati JSON e vuoi generare uno schema di partenza, diversi strumenti automatizzano il processo:
- quicktype.io — inferisce schemi (e definizioni di tipo per TypeScript, Go, Python e altri) da JSON di esempio
- generate-schema (npm) —
generate-schema json schema.json data.json - Python: genson —
pip install genson, poiSchemaBuilderinferisce uno schema da uno o pi ù oggetti di esempio
Gli schemi generati sono un punto di partenza, non un prodotto finito. Inferiscono i tipi dai dati di esempio, ma non conoscono le tue regole di business — non possono dedurre che un campo string sia un'email, che un intero debba essere positivo, o che due campi siano mutuamente esclusivi. Rivedi e stringi sempre uno schema generato prima di usarlo in produzione.
Domande frequenti
A cosa serve JSON Schema?
A descrivere e validare la struttura dei dati JSON — quali chiavi sono obbligatorie, di che tipo deve essere ogni valore e quali valori sono ammessi. Alimenta OpenAPI, l'autocomplete IDE di package.json/tsconfig.json, la generazione di form e i contratti di pipeline dati.
Qual è la differenza tra JSON e JSON Schema?
JSON sono i dati; JSON Schema è un documento JSON separato che descrive come dovrebbero essere i dati validi. Se sei nuovo al formato stesso, parti da Cos'è JSON?.
Quale draft di JSON Schema dovrei usare?
Draft 2020-12 è quello attuale e raccomandato per i nuovi schemi; Draft-07 è ancora comune grazie all'ampio supporto degli strumenti. Dichiara sempre la versione con $schema per non lasciare i validatori a indovinare.
Come valido JSON rispetto a uno schema?
Usa Ajv in JavaScript, la libreria jsonschema in Python (esempi sopra), o un validatore web. Per prima cosa, per confermare che il JSON sia almeno sintatticamente valido, vedi Come validare JSON o passalo per il validatore.
JSON Schema valida format (email, date-time, uri…)?
Nel Draft 2020-12 / 2019-09 la parola chiave format è annotazione per impostazione predefinita — i validatori la impongono solo se configurati. Con Ajv, registra ajv-formats e abilita la format assertion per rifiutare davvero i valori malformati.
Conclusione
JSON Schema trasforma la documentazione informale («questo campo dovrebbe essere un numero») in un contratto verificabile da macchine che i validatori possono far rispettare in modo coerente tra linguaggi, team e sistemi. Il vocabolario centrale — type, properties, required, items, enum — copre la grande maggioranza dei casi reali. Funzionalità più avanzate come $ref, parole chiave di composizione e format si occupano del resto.
Parti da uno schema minimo che imponga solo ciò che hai davvero bisogno di imporre. Aggiungi vincoli in modo incrementale man mano che la tua comprensione dei dati si consolida. Uno schema che rifiuta dati validi è peggio di nessuno schema.
Se il JSON che stai validando ha errori di sintassi prima ancora di arrivare al validatore di schema, risolvi prima quelli — un validatore di schema richiede JSON sintatticamente corretto in input. Quando il JSON è pulito, validalo e poi applica il tuo schema.