← Torna al Blog

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 Team15 min di letturaadvanced
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

15 min di lettura

# 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

Librerie consigliate:
  • JavaScript: ajv
  • Python: jsonschema, pydantic
  • Strumenti: quicktype, generate-schema

Inizia a usare JSON Schema nei tuoi progetti per codice più robusto e manutenibile!

Share:

Articoli Correlati

Read in English