JSON Schema: Validare API come un Pro
JSON Schema: validare API come un professionista. Guida completa per definire strutture dati, validazione automatica e documentazione delle tue API REST.
Introduzione a JSON Schema
JSON Schema è uno standard potente per definire la struttura, i vincoli e la validazione dei dati JSON. Nel mondo delle API moderne, dove JSON è il formato di scambio dati predominante, avere uno schema formale che descrive i dati attesi è fondamentale per garantire qualità, documentazione e interoperabilità tra sistemi.
Questa guida completa ti insegnerà a usare JSON Schema come un professionista, dalla sintassi base alle tecniche avanzate utilizzate nelle API enterprise.
Perché Usare JSON Schema
Validazione Automatica
JSON Schema permette di validare automaticamente i dati in ingresso e in uscita dalle API. Questo significa che errori nei dati vengono catturati immediatamente, prima che causino problemi nell'applicazione.
- Input validation: Verifica che i dati inviati dai client siano corretti
- Output validation: Garantisce che le risposte API rispettino il contratto
- Testing: Genera automaticamente test cases basati sullo schema
- Documentazione: Lo schema stesso è documentazione vivente
Documentazione Automatica
Con JSON Schema puoi generare automaticamente documentazione API usando tool come Swagger/OpenAPI, Redoc o Stoplight. Lo schema diventa la single source of truth per tutta la documentazione.
Sintassi Base
Struttura di Uno Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"description": "Schema per validare oggetti utente",
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "ID univoco dell'utente"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
}
},
"required": ["id", "name", "email"]
}
Tipi di Dati
| Tipo | Descrizione | Esempio |
|---|---|---|
| string | Stringa di testo | "hello" |
| number | Numero (inclusi decimali) | 3.14 |
| integer | Numero intero | 42 |
| boolean | Vero o falso | true |
| array | Lista di elementi | [1, 2, 3] |
| object | Oggetto con proprietà | {"key": "value"} |
| null | Valore nullo | null |
Vincoli per Tipo
Vincoli per Stringhe
{
"type": "string",
"minLength": 1, // Lunghezza minima
"maxLength": 255, // Lunghezza massima
"pattern": "^[A-Z]{2}$", // Regex pattern
"format": "email" // Formato predefinito
}
// Formati disponibili:
// email, uri, uri-reference, uuid
// date, date-time, time
// hostname, ipv4, ipv6
// regex, json-pointer
Vincoli per Numeri
{
"type": "number",
"minimum": 0, // Valore minimo (incluso)
"maximum": 100, // Valore massimo (incluso)
"exclusiveMinimum": 0, // Valore minimo (escluso)
"exclusiveMaximum": 100, // Valore massimo (escluso)
"multipleOf": 0.01 // Deve essere multiplo di
}
Vincoli per Array
{
"type": "array",
"items": { "type": "string" }, // Schema per ogni elemento
"minItems": 1, // Minimo elementi
"maxItems": 10, // Massimo elementi
"uniqueItems": true // Elementi unici
}
// Array con elementi tipizzati per posizione (tuple)
{
"type": "array",
"prefixItems": [
{ "type": "string" }, // primo elemento
{ "type": "number" } // secondo elemento
],
"items": false // non altri elementi
}
Vincoli per Oggetti
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["name"], // Proprietà obbligatorie
"additionalProperties": false, // Blocca proprietà extra
"minProperties": 1, // Minimo proprietà
"maxProperties": 10 // Massimo proprietà
}
Composizione di Schema
$ref per Riutilizzo
// definitions.schema.json
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string" }
}
}
}
}
// user.schema.json
{
"type": "object",
"properties": {
"name": { "type": "string" },
"address": { "$ref": "#/$defs/address" },
"billingAddress": { "$ref": "#/$defs/address" }
}
}
allOf, anyOf, oneOf
// allOf: deve soddisfare TUTTI gli schema
{
"allOf": [
{ "$ref": "#/$defs/baseUser" },
{ "properties": { "role": { "const": "admin" } } }
]
}
// anyOf: deve soddisfare ALMENO UNO
{
"anyOf": [
{ "type": "string" },
{ "type": "number" }
]
}
// oneOf: deve soddisfare ESATTAMENTE UNO
{
"oneOf": [
{ "properties": { "type": { "const": "email" }, "email": { "type": "string" } } },
{ "properties": { "type": { "const": "sms" }, "phone": { "type": "string" } } }
]
}
Condizionali: if/then/else
{
"type": "object",
"properties": {
"paymentMethod": { "enum": ["card", "bank"] }
},
"if": {
"properties": { "paymentMethod": { "const": "card" } }
},
"then": {
"properties": {
"cardNumber": { "type": "string", "pattern": "^[0-9]{16}$" }
},
"required": ["cardNumber"]
},
"else": {
"properties": {
"iban": { "type": "string", "pattern": "^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$" }
},
"required": ["iban"]
}
}
Integrazione con OpenAPI
# openapi.yaml
openapi: 3.1.0
info:
title: User API
version: 1.0.0
paths:
/users:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUser'
responses:
'201':
description: User created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
schemas:
CreateUser:
type: object
properties:
name:
type: string
minLength: 1
email:
type: string
format: email
required: [name, email]
User:
allOf:
- $ref: '#/components/schemas/CreateUser'
- type: object
properties:
id:
type: integer
required: [id]
Validazione in JavaScript
// Con Ajv (Another JSON Validator)
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({ allErrors: true });
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']
};
const validate = ajv.compile(schema);
const data = { name: 'Mario', email: 'mario@example.com', age: 30 };
const valid = validate(data);
if (!valid) {
console.log(validate.errors);
// [{ keyword: 'required', params: { missingProperty: 'email' }, ... }]
}
Validazione in Python
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"]
}
data = {"name": "Mario", "email": "mario@example.com", "age": 30}
try:
validate(instance=data, schema=schema)
print("Valid!")
except ValidationError as e:
print(f"Invalid: {e.message}")
Best Practices
Organizzazione Schema
- Un file per schema: Mantieni schema separati e riferiscili con $ref
- Usa $defs: Definisci componenti riutilizzabili
- Versioning: Includi la versione nell'URL dello schema
- Descrizioni: Aggiungi description a ogni proprietà
Validazione Robusta
// additionalProperties: false per API strette
{
"type": "object",
"properties": {
"name": { "type": "string" }
},
"additionalProperties": false // Rifiuta proprietà non definite
}
// propertyNames per validare i nomi delle chiavi
{
"type": "object",
"propertyNames": {
"pattern": "^[a-z_]+$" // Solo lettere minuscole e underscore
}
}
Generare Schema Automaticamente
// Da TypeScript (typescript-json-schema)
npx typescript-json-schema tsconfig.json User --out user.schema.json
// Da dati JSON (quicktype)
npx quicktype sample.json -o schema.json --lang schema
// Da Zod (zod-to-json-schema)
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
const UserSchema = z.object({
name: z.string().min(1),
email: z.string().email()
});
const jsonSchema = zodToJsonSchema(UserSchema);
Strumenti Correlati
Per lavorare con JSON Schema:
- JSON Formatter - Formatta e valida JSON
- JSON Schema Converter - Genera schema da JSON
- Diff Checker - Confronta versioni schema
Conclusione
JSON Schema è essenziale per API professionali. Punti chiave:
- Definisci schema per tutti i dati in input e output
- Usa $ref per riutilizzare definizioni comuni
- Integra la validazione nel middleware API
- Genera documentazione automaticamente con OpenAPI
- Testa gli schema con dati validi e invalidi
Investire tempo nella definizione degli schema ripaga enormemente in termini di qualità del codice e riduzione dei bug.
Per altri strumenti utili, esplora i nostri tool online gratuiti. Per la specifica completa, consulta json-schema.org.