Comprendere JSON Schema: Validazione e documentazione dati
Guida completa a JSON Schema: validazione dati, tipi, vincoli, pattern, esempi pratici e librerie. Impara a validare e documentare API JSON professionalmente.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# Comprendere JSON Schema: Validazione e documentazione dati
JSON Schema è un potente standard per descrivere e validare la struttura dei dati JSON. Questa guida completa ti insegnerà a usare JSON Schema per validare dati, documentare API e garantire la qualità del codice.
Cos'è JSON Schema?
JSON Schema è:
- Standard di validazione: Definisce regole per dati JSON
- Documentazione: Descrive la struttura attesa
- Contratto di dati: Specifica formato per API
- Tool di qualità: Previene errori nei dati
Esempio base
Schema:{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"nome": {
"type": "string"
},
"età": {
"type": "integer",
"minimum": 0
}
},
"required": ["nome"]
}
Dati validi:
{
"nome": "Marco",
"età": 30
}
Dati non validi:
{
"età": 30
}
// Errore: "nome" è richiesto
Tipi di dati base
string
{
"type": "string",
"minLength": 1,
"maxLength": 100,
"pattern": "^[A-Za-z]+$"
}
Esempi:
// ✅ Valido
"Marco"
// ❌ Non valido
"" // Troppo corto
"Marco123" // Contiene numeri
number / integer
{
"type": "integer",
"minimum": 0,
"maximum": 150,
"multipleOf": 5
}
Esempi:
// ✅ Valido
0, 5, 10, 150
// ❌ Non valido
-1 // Sotto minimum
151 // Sopra maximum
7 // Non multiplo di 5
boolean
{
"type": "boolean"
}
Esempi:
// ✅ Valido
true
false
// ❌ Non valido
"true" // Stringa, non booleano
null
{
"type": "null"
}
array
{
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
Esempi:
// ✅ Valido
["mela", "banana", "arancia"]
// ❌ Non valido
[] // Troppo pochi elementi
["mela", "banana", "mela"] // Duplicati
object
{
"type": "object",
"properties": {
"nome": { "type": "string" },
"età": { "type": "integer" }
},
"required": ["nome"],
"additionalProperties": false
}
Schema completo: Utente
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/schemas/utente.json",
"title": "Utente",
"description": "Schema per un utente del sistema",
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID univoco utente",
"minimum": 1
},
"username": {
"type": "string",
"description": "Nome utente unico",
"pattern": "^[a-zA-Z0-9_]{3,20}$",
"minLength": 3,
"maxLength": 20
},
"email": {
"type": "string",
"description": "Indirizzo email",
"format": "email"
},
"password": {
"type": "string",
"description": "Password (minimo 8 caratteri)",
"minLength": 8
},
"età": {
"type": "integer",
"description": "Età dell'utente",
"minimum": 18,
"maximum": 120
},
"ruoli": {
"type": "array",
"description": "Ruoli assegnati",
"items": {
"type": "string",
"enum": ["user", "admin", "moderator"]
},
"minItems": 1,
"uniqueItems": true
},
"profilo": {
"type": "object",
"properties": {
"nome": { "type": "string" },
"cognome": { "type": "string" },
"bio": { "type": "string", "maxLength": 500 },
"avatar_url": {
"type": "string",
"format": "uri"
}
},
"required": ["nome", "cognome"]
},
"attivo": {
"type": "boolean",
"description": "Stato account",
"default": true
},
"creato_il": {
"type": "string",
"description": "Data creazione account",
"format": "date-time"
}
},
"required": ["id", "username", "email", "password"],
"additionalProperties": false
}
Dati validi per questo schema:
{
"id": 12345,
"username": "marco_rossi",
"email": "marco@example.com",
"password": "SecurePass123!",
"età": 30,
"ruoli": ["user", "moderator"],
"profilo": {
"nome": "Marco",
"cognome": "Rossi",
"bio": "Sviluppatore full-stack",
"avatar_url": "https://example.com/avatar.jpg"
},
"attivo": true,
"creato_il": "2026-01-26T10:30:00Z"
}
Vincoli avanzati
pattern (regex)
{
"type": "string",
"pattern": "^[0-9]{5}$"
}
// Accetta solo 5 cifre: 12345 ✅, ABC12 ❌
Esempi comuni:
{
"cap_italiano": {
"type": "string",
"pattern": "^[0-9]{5}$"
},
"codice_fiscale": {
"type": "string",
"pattern": "^[A-Z]{6}[0-9]{2}[A-Z][0-9]{2}[A-Z][0-9]{3}[A-Z]$"
},
"telefono_italiano": {
"type": "string",
"pattern": "^\+39\s?[0-9]{2,4}\s?[0-9]{6,8}$"
}
}
format
{
"email": {
"type": "string",
"format": "email"
},
"website": {
"type": "string",
"format": "uri"
},
"data_nascita": {
"type": "string",
"format": "date"
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"indirizzo_ip": {
"type": "string",
"format": "ipv4"
}
}
enum
{
"stato": {
"type": "string",
"enum": ["attivo", "sospeso", "cancellato"]
},
"priorità": {
"type": "integer",
"enum": [1, 2, 3, 4, 5]
}
}
const
{
"versione_api": {
"type": "string",
"const": "v1"
}
}
// Accetta SOLO "v1"
Schema composition
allOf (AND)
{
"allOf": [
{
"type": "object",
"properties": {
"nome": { "type": "string" }
}
},
{
"type": "object",
"properties": {
"età": { "type": "integer" }
}
}
]
}
// Deve soddisfare ENTRAMBI gli schema
anyOf (OR inclusivo)
{
"anyOf": [
{ "type": "string" },
{ "type": "number" }
]
}
// Può essere stringa O numero (o entrambi compatibili)
oneOf (OR esclusivo)
{
"oneOf": [
{
"type": "object",
"properties": {
"tipo": { "const": "persona" },
"nome": { "type": "string" }
}
},
{
"type": "object",
"properties": {
"tipo": { "const": "azienda" },
"ragione_sociale": { "type": "string" }
}
}
]
}
// Deve corrispondere a ESATTAMENTE UNO schema
not
{
"not": {
"type": "null"
}
}
// Può essere qualsiasi cosa TRANNE null
Riferimenti ($ref)
Schema riutilizzabili
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"indirizzo": {
"type": "object",
"properties": {
"via": { "type": "string" },
"città": { "type": "string" },
"cap": { "type": "string", "pattern": "^[0-9]{5}$" }
},
"required": ["via", "città", "cap"]
}
},
"type": "object",
"properties": {
"indirizzo_casa": {
"$ref": "#/definitions/indirizzo"
},
"indirizzo_ufficio": {
"$ref": "#/definitions/indirizzo"
}
}
}
Riferimenti esterni
{
"type": "object",
"properties": {
"utente": {
"$ref": "https://example.com/schemas/utente.json"
}
}
}
Validazione in JavaScript
Con ajv (libreria più popolare)
const Ajv = require('ajv');
const ajv = new Ajv({ allErrors: true });
// Schema
const schema = {
type: "object",
properties: {
nome: { type: "string", minLength: 1 },
età: { type: "integer", minimum: 0, maximum: 150 },
email: { type: "string", format: "email" }
},
required: ["nome", "età"]
};
// Compila schema
const validate = ajv.compile(schema);
// Dati da validare
const dati = {
nome: "Marco",
età: 30,
email: "marco@example.com"
};
// Valida
const valid = validate(dati);
if (valid) {
console.log("✅ Dati validi!");
} else {
console.log("❌ Errori di validazione:");
validate.errors.forEach(error => {
console.log( - ${error.instancePath}: ${error.message});
});
}
Validazione dati non validi
const datiInvalidi = {
nome: "", // Troppo corto
età: 200, // Troppo grande
email: "invalid-email" // Formato errato
};
const valid = validate(datiInvalidi);
console.log(validate.errors);
/
[
{
instancePath: '/nome',
message: 'must NOT have fewer than 1 characters'
},
{
instancePath: '/età',
message: 'must be <= 150'
},
{
instancePath: '/email',
message: 'must match format "email"'
}
]
/
Validazione Express middleware
const Ajv = require('ajv');
const ajv = new Ajv();
function validateSchema(schema) {
const validate = ajv.compile(schema);
return (req, res, next) => {
const valid = validate(req.body);
if (!valid) {
return res.status(400).json({
error: "Validazione fallita",
details: validate.errors
});
}
next();
};
}
// Uso in route
const userSchema = {
type: "object",
properties: {
username: { type: "string", minLength: 3 },
email: { type: "string", format: "email" },
password: { type: "string", minLength: 8 }
},
required: ["username", "email", "password"]
};
app.post('/api/users',
validateSchema(userSchema),
(req, res) => {
// Body già validato
const user = req.body;
// ... crea utente
res.json({ success: true });
}
);
Validazione in Python
Con jsonschema
from jsonschema import validate, ValidationError
# Schema
schema = {
"type": "object",
"properties": {
"nome": {"type": "string", "minLength": 1},
"età": {"type": "integer", "minimum": 0, "maximum": 150},
"email": {"type": "string", "format": "email"}
},
"required": ["nome", "età"]
}
# Dati validi
dati_validi = {
"nome": "Marco",
"età": 30,
"email": "marco@example.com"
}
try:
validate(instance=dati_validi, schema=schema)
print("✅ Dati validi!")
except ValidationError as e:
print(f"❌ Errore: {e.message}")
print(f" Path: {list(e.path)}")
Validazione con Pydantic
from pydantic import BaseModel, EmailStr, Field, validator
from typing import List, Optional
class Indirizzo(BaseModel):
via: str
città: str
cap: str = Field(..., regex=r'^[0-9]{5}$')
class Utente(BaseModel):
id: int = Field(..., gt=0)
username: str = Field(..., min_length=3, max_length=20)
email: EmailStr
password: str = Field(..., min_length=8)
età: int = Field(..., ge=18, le=120)
ruoli: List[str] = []
indirizzo: Optional[Indirizzo] = None
attivo: bool = True
@validator('username')
def username_alfanumerico(cls, v):
if not v.replace('_', '').isalnum():
raise ValueError('username deve essere alfanumerico')
return v
@validator('password')
def password_forte(cls, v):
if not any(c.isupper() for c in v):
raise ValueError('password deve contenere maiuscole')
if not any(c.isdigit() for c in v):
raise ValueError('password deve contenere numeri')
return v
# Uso
try:
utente = Utente(
id=1,
username="marco_rossi",
email="marco@example.com",
password="Secure123",
età=30,
ruoli=["user", "admin"]
)
print("✅ Utente valido!")
print(utente.json(indent=2))
except Exception as e:
print(f"❌ Validazione fallita: {e}")
Generazione automatica schema
Da JSON esistente (JavaScript)
const generateSchema = require('generate-schema');
const dati = {
nome: "Marco",
età: 30,
email: "marco@example.com",
hobby: ["programmazione", "viaggi"]
};
const schema = generateSchema.json('Utente', dati);
console.log(JSON.stringify(schema, null, 2));
/
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"nome": { "type": "string" },
"età": { "type": "number" },
"email": { "type": "string" },
"hobby": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["nome", "età", "email", "hobby"]
}
/
Da TypeScript (quicktype)
# Installa quicktype
npm install -g quicktype
# Genera schema da JSON
quicktype data.json -o schema.json --lang schema
Best practices
1. Usa $schema e $id
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/schemas/user.json",
"title": "User Schema",
"description": "Schema for user objects"
}
2. Fornisci description
{
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Indirizzo email dell'utente. Deve essere univoco nel sistema."
}
}
}
3. Usa default values
{
"properties": {
"attivo": {
"type": "boolean",
"default": true,
"description": "Stato account utente"
},
"ruolo": {
"type": "string",
"default": "user",
"enum": ["user", "admin", "moderator"]
}
}
}
4. Limita additionalProperties
{
"type": "object",
"properties": {
"nome": { "type": "string" }
},
"additionalProperties": false
}
// Impedisce proprietà extra non definite
5. Usa examples
{
"type": "object",
"properties": {
"nome": { "type": "string" }
},
"examples": [
{
"nome": "Marco Rossi"
},
{
"nome": "Laura Bianchi"
}
]
}
Casi d'uso reali
1. Validazione API Request
// POST /api/orders
const orderSchema = {
type: "object",
properties: {
customer_id: { type: "integer", minimum: 1 },
items: {
type: "array",
minItems: 1,
items: {
type: "object",
properties: {
product_id: { type: "integer" },
quantity: { type: "integer", minimum: 1 },
price: { type: "number", minimum: 0 }
},
required: ["product_id", "quantity", "price"]
}
},
shipping_address: {
type: "object",
properties: {
street: { type: "string" },
city: { type: "string" },
zip: { type: "string", pattern: "^[0-9]{5}$" }
},
required: ["street", "city", "zip"]
}
},
required: ["customer_id", "items", "shipping_address"]
};
2. Configurazione applicazione
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "App Config",
"type": "object",
"properties": {
"app": {
"type": "object",
"properties": {
"nome": { "type": "string" },
"porta": { "type": "integer", "minimum": 1024, "maximum": 65535 },
"debug": { "type": "boolean", "default": false }
},
"required": ["nome", "porta"]
},
"database": {
"type": "object",
"properties": {
"host": { "type": "string" },
"porta": { "type": "integer" },
"nome_db": { "type": "string" }
},
"required": ["host", "nome_db"]
}
},
"required": ["app", "database"]
}
Conclusione
JSON Schema è essenziale per:
- ✅ Validare dati API
- ✅ Documentare strutture dati
- ✅ Garantire qualità dati
- ✅ Prevenire errori runtime
- ✅ Generare documentazione
- JavaScript: ajv
- Python: jsonschema, pydantic
- Strumenti: quicktype, generate-schema
Inizia a usare JSON Schema nei tuoi progetti per codice più robusto e manutenibile!
Articoli Correlati
Cos'è JSON? Guida completa per principianti
Scopri cos'è JSON, la sua sintassi, i tipi di dati e i casi d'uso. Una guida completa e adatta ai principianti per comprendere JavaScript Object Notation.
Python e JSON: Guida completa alla manipolazione dati
Impara a lavorare con JSON in Python: parsing, serializzazione, validazione, file I/O e best practices. Include esempi pratici con json, jsonschema e pydantic.
API JSON e servizi REST: Guida completa per sviluppatori
Guida completa alle API JSON e REST: metodi HTTP, autenticazione, best practices, esempi pratici con fetch e axios. Impara a creare e consumare API moderne.