Skip to content
Torna al blog
Tutorial

Validazione JSON Schema online nel 2026: guida Ajv, Python e browser

Valida JSON con uno schema in Node, Python e nel browser. Funzionalità Draft 2020-12, pattern reali di API ed esempi copia-incolla. Provalo gratis.

12 min di lettura

Validazione JSON Schema: come validare JSON in Node, Python e nel browser (2026)

In sintesi. JSON Schema è un contratto per i dati JSON: dichiari i tipi dei campi, quali chiavi sono obbligatorie e i vincoli, poi un validatore verifica se un documento JSON rispetta quel contratto. Usa Ajv in Node per la validazione più rapida, la libreria jsonschema in Python per schemi portabili, e includi Ajv nel browser per dare feedback immediato su form e configurazioni. Per i nuovi progetti nel 2026, parti da Draft 2020-12.

Sotto trovi l’esempio funzionante più piccolo, i pattern end-to-end nei tre runtime e le trappole reali che producono i bug del tipo “la validazione passa, ma in produzione i dati vengono rifiutati”.

Cos’è (e cosa non è) JSON Schema

Una definizione in una frase

Uno JSON Schema è un documento JSON che descrive la forma di altri documenti JSON. Un validatore legge lo schema e i dati, poi conferma la conformità o restituisce i percorsi che hanno fallito.

L’esempio utile più piccolo:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": { "name": { "type": "string" } },
  "required": ["name"]
}

{"name": "Alice"} passa. {"age": 30} fallisce (manca name). {"name": 42} fallisce (name non è una stringa). Questo è l’intero modello mentale.

JSON Schema vs validazione della sintassi JSON

Due problemi diversi, spesso confusi.

DimensioneControllo sintattico JSONValidazione JSON Schema
Cosa controllaÈ un documento JSON valido?Il JSON corrisponde al contratto?
Cosa catturaVirgole mancanti, apici singoli, commentiTipi sbagliati, campi obbligatori mancanti, valori fuori intervallo
StrumentiJSON.parse(), Formattatore JSONAjv, jsonschema (Python), fastjsonschema
Quando ti servePer primo, prima del parsingSubito dopo il parsing, prima della logica di business

Di solito si fanno entrambi: formatti il payload nel Formattatore JSON per confermare che venga interpretato, poi lo passi a uno schema per verificare che rispetti il contratto.

JSON Schema vs JSONPath, JSON Patch, jq e TypeScript

Cinque strumenti condividono lo stesso spazio di problemi. La matrice decisionale:

StrumentoDomanda a cui rispondeQuando usarlo
JSON SchemaQuesto JSON corrisponde alla struttura attesa?Validazione di input API, file di configurazione, payload di form
JSONPathCome estraggo un valore da questo JSON?Estrazione di campi annidati, letture in batch
JSON Patch (RFC 6902)Come descrivo la differenza fra A e B?Editing collaborativo, sincronizzazione incrementale
jqCome elaboro JSON dalla riga di comando?Script di shell, pipeline di log, controlli CI
Tipi TypeScriptIl mio codice usa correttamente questa forma?Garanzie a tempo di compilazione all’interno di un’unica codebase

La distinzione che conta: JSON Schema valida dati sconosciuti a runtime, TypeScript valida codice noto a tempo di compilazione. TypeScript non può aiutarti con il JSON che arriva da un webhook di terze parti o da un incolla dell’utente; è esattamente per questo che esiste JSON Schema. Zod e Pydantic occupano una via di mezzo (tipi a tempo di compilazione più validazione a runtime), e li trattiamo più avanti.

JSON Schema vs OpenAPI

Un equivoco diffuso è che OpenAPI sostituisca JSON Schema. Non è così. OpenAPI usa JSON Schema al suo interno per descrivere i corpi di richiesta e risposta, poi sopra aggiunge percorsi, parametri, schemi di sicurezza e URL del server. Lo schema è il contratto sulla forma dei dati; OpenAPI è il contratto sull’API che lo avvolge.

DimensioneJSON SchemaOpenAPI
AmbitoForma di un singolo documento JSONForma di un’intera API HTTP
DipendenzeNessuna (lo schema è JSON autonomo)Importa JSON Schema per la definizione dei corpi
Abbinamento di versioneDraft 7 / Draft 2019-09 / Draft 2020-12OpenAPI 3.0 usa un sottoinsieme di Draft 4; OpenAPI 3.1 usa Draft 2020-12 nativamente
Uso tipicoFile di configurazione, envelope di messaggi, validazione di form, contratti su singolo payloadDesign di API REST, generazione di SDK, mock server, contract testing
Generazione di codiceLimitata (alcuni strumenti tipo quicktype)Ecosistema maturo (openapi-generator, oapi-codegen, SDK dei vendor)
Gestione del contrattoUn file per forma, nessun routingPercorsi, operazioni, flussi di autenticazione, endpoint versionati in un unico documento

Scegli JSON Schema quando l’artefatto che ti interessa è un singolo documento: un payload di webhook, un file di configurazione, un messaggio di coda o un form. Non c’è una superficie HTTP da descrivere, quindi OpenAPI è solo overhead.

Scegli OpenAPI quando pubblichi un’API HTTP e vuoi un solo documento che alimenti documentazione, generazione di SDK, mock server e contract test. Definisci prima i tuoi schemi come file JSON Schema indipendenti in una directory schemas/, poi referenziali con $ref dal documento OpenAPI. Così gli schemi restano riutilizzabili anche fuori dal contesto API.

L’abbinamento di versione fa inciampare i team. OpenAPI 3.0 usa un sottoinsieme di Draft 4, quindi non puoi usare keyword di Draft 2020-12 come prefixItems o unevaluatedProperties dentro un documento 3.0: i generatori le ignorano in silenzio. OpenAPI 3.1 è un sovrainsieme di Draft 2020-12, quindi tutto ciò che è valido in 2020-12 è valido in 3.1. Se puoi scegliere, punta su OpenAPI 3.1 e scrivi schemi Draft 2020-12 ovunque.

Il tuo primo JSON Schema (5 minuti)

Le keyword da imparare per prime

Coprirai l’80% dei casi con queste:

{
  "type": "object",
  "properties": {
    "id":       { "type": "integer", "minimum": 1 },
    "email":    { "type": "string", "format": "email" },
    "age":      { "type": "integer", "minimum": 0, "maximum": 150 },
    "tags":     { "type": "array", "items": { "type": "string" }, "minItems": 1 },
    "role":     { "enum": ["admin", "editor", "viewer"] },
    "metadata": { "type": "object", "additionalProperties": true }
  },
  "required": ["id", "email"],
  "additionalProperties": false
}

Il vocabolario:

  • type: string, number, integer, boolean, null, array, object
  • properties con required: dichiara i campi e marca quelli che devono essere presenti
  • enum o const: vincola a un insieme fisso o a un singolo letterale
  • minimum, maximum, multipleOf: limiti numerici
  • minLength, maxLength, pattern: lunghezza stringa e regex
  • minItems, maxItems, uniqueItems: forma dell’array
  • additionalProperties: false: rifiuta chiavi non dichiarate (impostalo sempre sui contratti di input)

Esempi di JSON Schema per caso d’uso

Le keyword qui sopra compaiono in combinazioni diverse a seconda di cosa stai validando. Alcune forme rappresentative:

Corpo di richiesta API: un endpoint di registrazione che accetta email e password.

{
  "type": "object",
  "properties": {
    "email":    { "type": "string", "format": "email" },
    "password": { "type": "string", "minLength": 8, "maxLength": 128 }
  },
  "required": ["email", "password"],
  "additionalProperties": false
}

File di configurazione: una configurazione di logger che vincola il livello a un insieme fisso.

{
  "type": "object",
  "properties": {
    "level":  { "enum": ["debug", "info", "warn", "error"] },
    "output": { "type": "string", "default": "stdout" }
  },
  "required": ["level"],
  "additionalProperties": false
}

Payload di form con regole condizionali: quando accountType è "business", taxId diventa obbligatorio.

{
  "type": "object",
  "properties": {
    "accountType": { "enum": ["personal", "business"] },
    "taxId":       { "type": "string" }
  },
  "if":   { "properties": { "accountType": { "const": "business" } } },
  "then": { "required": ["taxId"] }
}

Record JSON da riga CSV: una riga di una tabella di ordini esportata.

{
  "type": "object",
  "properties": {
    "orderId":   { "type": "string", "pattern": "^ORD-[0-9]{6}$" },
    "orderedOn": { "type": "string", "format": "date" },
    "totalUsd":  { "type": "number", "minimum": 0 }
  },
  "required": ["orderId", "orderedOn", "totalUsd"]
}

Envelope di evento webhook: oneOf discrimina sul letterale type, così ogni variante di evento ha la propria forma di payload.

{
  "oneOf": [
    { "properties": { "type": { "const": "order.created" }, "data": { "$ref": "#/$defs/order" } } },
    { "properties": { "type": { "const": "order.refunded" }, "data": { "$ref": "#/$defs/refund" } } }
  ]
}

Questi cinque esempi coprono la gran parte di ciò che i team scrivono in pratica. Copia il caso più vicino e adatta i nomi dei campi: il vocabolario delle keyword resta lo stesso.

Validare senza installare nulla

Incolla schema e payload nel playground di ajv.js.org o jsonschemavalidator.net per un verdetto immediato. Se il JSON stesso sembra sospetto, passalo prima nel Formattatore JSON.

Validare in Node.js con Ajv

Installazione ed esempio in 12 righe

Ajv compila il tuo schema in una funzione ottimizzata alla prima compile, poi la riutilizza.

npm install ajv
import Ajv from "ajv";
const ajv = new Ajv();

const schema = {
  type: "object",
  properties: {
    name: { type: "string" },
    age:  { type: "integer", minimum: 0 }
  },
  required: ["name"]
};

const validate = ajv.compile(schema);
const data = { name: "Alice", age: 30 };

if (!validate(data)) console.log(validate.errors);
else                  console.log("OK");

Passare a Draft 2020-12

Il costruttore Ajv di default è ancora fissato a Draft 7 per compatibilità con il passato. Scegli 2020-12 in modo esplicito:

import Ajv2020 from "ajv/dist/2020";
const ajv = new Ajv2020({ strict: true, allErrors: true });

Ora prefixItems, unevaluatedProperties e $dynamicRef sono disponibili. Più avanti, nella sezione su Draft 2020-12, trovi cosa fa ciascuno.

Attivare la validazione di format

Questa è la stranezza di Ajv che inciampa più sviluppatori: format: "email" non fa nulla di default. La specifica considera format come informativo, quindi devi registrare il modulo dei format:

npm install ajv-formats
import addFormats from "ajv-formats";
addFormats(ajv);  // ora "format": "email" valida davvero

Senza questo passaggio, {"email": "not-an-email"} passa uno schema che richiede format: "email". Installa sempre ajv-formats in produzione.

Middleware Express sul campo

Un validatore per route, compilato all’avvio:

import express from "express";
import Ajv2020 from "ajv/dist/2020";
import addFormats from "ajv-formats";

const ajv = new Ajv2020({ allErrors: true });
addFormats(ajv);

const validateUser = ajv.compile({
  type: "object",
  properties: {
    email: { type: "string", format: "email" },
    age:   { type: "integer", minimum: 13 }
  },
  required: ["email"],
  additionalProperties: false
});

const app = express();
app.use(express.json());

app.post("/users", (req, res) => {
  if (!validateUser(req.body)) {
    return res.status(400).json({ errors: validateUser.errors });
  }
  // ... logica di business
  res.status(201).json({ ok: true });
});

L’errore singolo più costoso: chiamare ajv.compile(schema) dentro l’handler della richiesta. Compila una volta sola a livello di modulo, poi riutilizza la funzione restituita. Ricompilare a ogni richiesta abbatte il throughput di 50 volte o più.

Validare in Python con jsonschema

Installazione e uso di base

pip install jsonschema
from jsonschema import validate, ValidationError

schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age":  {"type": "integer", "minimum": 0}
    },
    "required": ["name"]
}

try:
    validate(instance={"name": "Alice", "age": 30}, schema=schema)
    print("OK")
except ValidationError as e:
    print("FAIL:", e.message, "at", list(e.absolute_path))

Raccogliere tutti gli errori con Draft202012Validator

validate() solleva un’eccezione al primo errore. Per elencare ogni problema in una volta sola (utile per le risposte dei form), usa iter_errors:

from jsonschema import Draft202012Validator

validator = Draft202012Validator(schema)
errors = sorted(validator.iter_errors(instance), key=lambda e: e.path)
for err in errors:
    print(f"  - {'/'.join(map(str, err.absolute_path))}: {err.message}")

Ora l’utente corregge tutto in una sola volta, invece di rimbalzare avanti e indietro col server.

jsonschema vs Pydantic: quando scegliere quale

Due buone librerie Python per due problemi diversi.

DimensionejsonschemaPydantic v2
Formato dello schemaUn dizionario JSON (lo schema è dato)Una classe Python con type hint
PerformanceInterpretato, ~10–100× più lento di PydanticCore in Rust, il più veloce dell’ecosistema
Portabilità cross-languageSì (lo stesso schema funziona in JS, Go, Rust)No (solo Python)
Integrazione FastAPI / modelli nativiConversione manualeIntegrata
Keyword complete di Draft 2020-12 ($dynamicRef, ecc.)CompletaParziale

La regola che tiene in produzione: usa jsonschema per i contratti cross-language (OpenAPI, API pubbliche, webhook), usa Pydantic per i servizi Python interni. Molti team mettono in campo entrambi: jsonschema al gateway per applicare il contratto, Pydantic a livello applicativo per la logica di business tipata. Lo schema rimane l’artefatto portabile, lo stesso che daresti in pasto ad Ajv.

Validare nel browser

Perché validare lato client

In ordine di importanza:

  1. UX: il feedback istantaneo mentre l’utente scrive batte qualunque round trip al server.
  2. Banda: gli errori evidenti non lasciano mai il browser.
  3. Igiene di sicurezza: riduce il volume di spazzatura che arriva al backend, anche se non sostituisce la validazione lato server.

Non fidarti mai della sola validazione lato client. Rivalida sempre sul server.

Includere Ajv nel bundle del browser

npm install ajv ajv-formats
import Ajv2020 from "ajv/dist/2020";
import addFormats from "ajv-formats";

const ajv = new Ajv2020({ allErrors: true });
addFormats(ajv);

export const validateForm = ajv.compile({
  type: "object",
  properties: {
    email:    { type: "string", format: "email" },
    password: { type: "string", minLength: 8 }
  },
  required: ["email", "password"]
});

Il bundle aggiunge circa 30 KB gzippati: non è poco, ma non è catastrofico. Si sceglie Ajv quando si vuole una sola definizione di schema condivisa fra server e client.

Alternative più leggere: Zod e Valibot

Se non ti serve l’ecosistema JSON Schema e sei già in TypeScript, un validatore TS-native ti dà bundle più piccoli e inferenza dei tipi più stretta:

import { z } from "zod";
const UserSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8)
});
const result = UserSchema.safeParse(data);
if (!result.success) console.log(result.error.issues);

Valibot pesa circa 3 KB gzippati con un’API simile. Sceglilo quando il peso del bundle è la cosa che pesa di più. Il rovescio della medaglia: nessuna delle due librerie produce JSON Schema. Se ti serve un’unica fonte di verità condivisa con backend, client di terze parti o generatori OpenAPI, resta su Ajv. Se invece tutto si gioca dentro il tuo TypeScript, Zod e Valibot sono più ergonomici.

Cosa aggiunge Draft 2020-12

prefixItems per la validazione delle tuple

Draft 7 esprimeva le tuple tramite items: [] più additionalItems. Draft 2020-12 le separa in modo netto:

{
  "type": "array",
  "prefixItems": [
    { "type": "string" },
    { "type": "number" }
  ],
  "items": false
}

["x", 42] passa. ["x", 42, "extra"] fallisce. Lo schema si legge esattamente per quello che fa.

unevaluatedProperties per gli schemi composti

C’è un bug sottile che colpisce qualunque team usi allOf o oneOf: additionalProperties: false controlla solo il livello immediato in cui appare. I sottoschemi gemelli dentro allOf dichiarano qualunque proprietà gli pare. La risposta di 2020-12 è unevaluatedProperties: false:

{
  "allOf": [
    { "$ref": "#/$defs/base" }
  ],
  "unevaluatedProperties": false
}

Così vengono rifiutate tutte le proprietà che nessuna branch ha valutato: di fatto il comportamento che la maggior parte degli sviluppatori si aspettava già da additionalProperties: false.

$dynamicRef per gli schemi ricorsivi

Chiunque abbia provato a dichiarare uno schema ad albero ricorsivo in Draft 7 conosce le contorsioni che servono. $dynamicRef insieme a $dynamicAnchor mette tutto in chiaro:

{
  "$dynamicAnchor": "node",
  "type": "object",
  "properties": {
    "value": { "type": "string" },
    "children": { "type": "array", "items": { "$dynamicRef": "#node" } }
  }
}

La ricorsione è dichiarativa e i discendenti possono sovrascriverla senza riscrivere $id.

Draft 7 vs 2020-12: quale scegliere

  • Nuovo progetto con toolchain moderna: Draft 2020-12.
  • Costruisci o consumi OpenAPI 3.1: 2020-12 è il dialetto nativo.
  • Lavori con OpenAPI 3.0 o servizi più vecchi: Draft 4 (OpenAPI 3.0 usa un sottoinsieme di Draft 4; non mescolare i dialetti).
  • Ti serve compatibilità ampia con i validatori (Postman, vecchi strumenti CI): Draft 7 resta il formato di interscambio più sicuro.

Oggi qualsiasi validatore moderno supporta 2020-12: Ajv, jsonschema per Python, jsonschema-rs, networknt/json-schema-validator di Java.

Pattern reali

Validazione dell’input di un’API

Il middleware Express visto sopra è la forma adatta alla produzione. Due abitudini da affiancargli: tieni tutti gli schemi in una directory schemas/ alla radice del repository, e aggiungi un passo CI che esegue ajv test (o l’equivalente Python) per validare gli schemi stessi contro la meta-schema di JSON Schema.

File di configurazione

Visual Studio Code è integrato con SchemaStore: ottieni autocomplete e validazione inline per package.json, tsconfig.json e decine di altri file. Aggiungi un campo $schema alle tue configurazioni e chi le apre nell’editor riceve lo stesso trattamento.

Fixture di test in CI

Le fixture di test marciscono. Qualcuno aggiorna un modello, una fixture resta com’era, il test continua a passare perché le asserzioni non avevano mai toccato il campo modificato. Per intercettarlo basta un controllo di schema prima delle asserzioni:

import { glob } from "glob";
const files = await glob("__tests__/fixtures/*.json");
for (const f of files) {
  const data = JSON.parse(await fs.readFile(f, "utf8"));
  if (!validate(data)) throw new Error(`${f}: ${ajv.errorsText(validate.errors)}`);
}

Quando il controllo di schema scatta, la mossa successiva è quasi sempre un diff strutturale. Porta la fixture in Confronta JSON contro un campione fresco di produzione per vedere cosa è andato alla deriva. Se timestamp e ID intasano il diff, applica gli schemi di esclusione percorsi della guida al diff JSON per separare il segnale dal rumore.

Payload dei webhook (Stripe, GitHub)

I webhook di terze parti sono uno dei punti dove applicare JSON Schema rende di più. Il webhook è un contratto, il provider può cambiarlo, e tu vuoi saperlo nel momento in cui succede. Stripe e GitHub pubblicano descrizioni OpenAPI da cui puoi estrarre JSON Schema. Valida gli eventi in ingresso, e un aggiornamento incompatibile fa scattare il monitoraggio invece di corrompere lo stato in silenzio.

Validazione di form guidata da schema

React Hook Form ha un adattatore @hookform/resolvers/ajv, e VeeValidate di Vue ha un plugin Ajv equivalente. Entrambi pilotano il rendering del form, i messaggi di errore e la validazione al submit a partire da un solo JSON Schema. Lo schema diventa l’unica fonte di verità, e la UI eredita le sue regole.

Messaggi di errore amichevoli

Perché i default sono ruvidi

Di base, Ajv restituisce errori come #/properties/email format must match "email". Va benissimo per chi sta debuggando un 400. Non serve a niente all’utente che sta compilando un form di checkout.

ajv-errors per messaggi personalizzati

npm install ajv-errors
import ajvErrors from "ajv-errors";
ajvErrors(ajv);

const schema = {
  type: "object",
  properties: { email: { type: "string", format: "email" } },
  required: ["email"],
  errorMessage: {
    properties: { email: "Inserisci un indirizzo email valido" },
    required: { email: "L'email è obbligatoria" }
  }
};

La keyword errorMessage resta dentro lo schema, così le regole di validazione e il testo per l’utente viaggiano nello stesso file.

ajv-i18n per errori tradotti

ajv-i18n distribuisce traduzioni dei messaggi di default in oltre 30 lingue. Una riga all’avvio e il tuo validatore parla spagnolo, francese, giapponese o qualunque locale ti serva. Funziona da fallback quando le tue sovrascritture errorMessage non coprono ogni vincolo.

Mappare i percorsi dello schema sui campi del form

Ogni errore di Ajv arriva con un instancePath come /users/0/email. La maggior parte delle librerie di form si aspetta percorsi puntati come users[0].email. Una riga sola:

const fieldPath = error.instancePath.replace(/^\//, "").replace(/\//g, ".");

In jsonschema di Python l’equivalente sta in error.absolute_path. Uniscilo con . e ottieni lo stesso effetto.

Cinque trappole che superano la validazione e poi mandano in crash la produzione

1. format è informativo per default

Senza ajv-formats più addFormats(ajv), ogni keyword format è un no-op. {"format": "email"} accetta "not-an-email". Installa sempre il pacchetto dei format in produzione.

2. additionalProperties ha default true

Senza additionalProperties: false, il tuo schema accetta qualunque campo non dichiarato. I client possono spedire campi extra che bypassano del tutto la validazione. Tieni additionalProperties: false come default sui contratti di input, e allenta solo quando hai un motivo preciso.

3. additionalProperties non si compone

Dentro allOf, oneOf o anyOf, additionalProperties: false ispeziona solo le proprietà del proprio livello. I sottoschemi gemelli sgusciano via. La risposta di Draft 2020-12 è unevaluatedProperties: false.

4. $ref remoto è un rischio in produzione

$ref: "https://example.com/schema.json" fa sì che Ajv vada in rete alla prima compilazione. Significa latenza, esposizione a DoS se l’host remoto si blocca, e una superficie d’attacco MITM. Inlinea tutti i target $ref, oppure caricali da disco a build time.

5. Gli schemi generati derivano dai dati reali

Strumenti come quicktype e typescript-json-schema generano schemi a partire da tipi esistenti. L’output è quasi sempre troppo permissivo: tutti i campi opzionali, additionalProperties aperto. Considera gli schemi generati come bozze, restringili a mano, e fai girare in CI un controllo che validi campioni reali di produzione contro lo schema (e viceversa) così la deriva emerge in fretta.

Performance: numeri e regole pratiche

  • Ajv (Node.js): i validatori compilati eseguono un controllo ben sotto il microsecondo. È il validatore JS production-grade più veloce in giro.
  • jsonschema (Python): interpretato, da 10 a 100 volte più lento di Pydantic. Quando pesa davvero, sostituiscilo con fastjsonschema, che genera codice Python e si avvicina ad Ajv.
  • Rust e Go: jsonschema-rs e xeipuuv/gojsonschema ti danno altre 2-5 volte rispetto ad Ajv al livello gateway.
  • Il singolo guadagno più grande è precompilare. Esegui ajv.compile(schema) una volta al caricamento del modulo, poi riutilizza il validatore restituito a ogni richiesta. Ricompilare a ogni richiesta uccide il throughput di 50 volte o più.

Domande frequenti

Cos’è la validazione JSON Schema spiegata in parole semplici?

La validazione JSON Schema controlla se un documento JSON rispetta un contratto. Il contratto (lo schema) è a sua volta JSON e dichiara tipi, campi obbligatori e vincoli. Un validatore legge lo schema e i dati, poi segnala “passa” oppure i percorsi che hanno fallito e perché.

Come valido JSON contro uno schema online?

Incolla schema e dati nel playground di ajv.js.org o in jsonschemavalidator.net per un verdetto immediato. Se il JSON sembra malformato, sistemalo prima nel Formattatore JSON; entrambi girano nel browser, senza upload.

Quale validatore JSON Schema è il più veloce nel 2026?

In Node, Ajv con validatori precompilati esegue un controllo in meno di un microsecondo. In Python, fastjsonschema genera codice e raggiunge throughput in classe Ajv. Al livello gateway, jsonschema-rs (Rust) e gojsonschema (Go) viaggiano da 2 a 5 volte più veloci di Ajv. Qualunque scelga, precompila una volta e riutilizza.

Qual è la differenza fra JSON Schema e i tipi TypeScript?

TypeScript controlla il codice che scrivi a tempo di compilazione. JSON Schema controlla JSON sconosciuto a runtime. TypeScript non può vedere il JSON che arriva da una risposta HTTP, da un file o da un incolla dell’utente; è esattamente per questo che esiste JSON Schema.

Devo usare Draft 2020-12 o Draft 7?

Per i nuovi progetti nel 2026, scegli Draft 2020-12. prefixItems, unevaluatedProperties e $dynamicRef risolvono problemi reali, e OpenAPI 3.1 usa 2020-12 nativamente. Resta su Draft 7 solo per compatibilità con Postman o servizi più vecchi. OpenAPI 3.0 usa un sottoinsieme di Draft 4: non mescolare dialetti.

Come genero un JSON Schema a partire da JSON esistente?

Hai un paio di opzioni. Incolla i campioni in quicktype.io o jsonschema.net; oppure esegui npx genson-js o pip install genson && genson sample.json da riga di comando; oppure scrivilo a mano. Gli schemi auto-generati sono troppo permissivi (tutti i campi opzionali, additionalProperties: true), quindi restringili sempre prima di trattarli come contratti.

JSON Schema può sostituire OpenAPI?

No. OpenAPI usa JSON Schema internamente per descrivere i corpi di richiesta e risposta, poi aggiunge percorsi, schemi di sicurezza, parametri e URL del server. Si compongono: scrivi i tuoi schemi, referenziali da un documento OpenAPI, ottieni contratti API completi.

JSON Schema è la stessa cosa di JSONPath o jq?

No, sono problemi diversi. JSON Schema valida la struttura (“questo JSON corrisponde al contratto?”). JSONPath e jq estraggono valori (“ogni nome di pod nella fase Running”). Validi con uno schema, interroghi con JSONPath o jq.

Perché la mia validazione Ajv passa ma in produzione i dati vengono rifiutati?

Quasi sempre i colpevoli sono questi: dimenticare ajv-formats (così format: "email" non ha mai davvero validato); omettere additionalProperties: false (e lasciare che campi extra del client passino indisturbati); oppure usare additionalProperties: false dentro allOf o oneOf e scoprire che non si compone. In quest’ultimo caso, passa a unevaluatedProperties: false.

Posso personalizzare i messaggi di errore di JSON Schema per gli utenti finali?

Sì. In Node, installa ajv-errors per incorporare errorMessage dentro lo schema, e ajv-i18n per le traduzioni in oltre 30 locale. In Python, jsonschema espone l’intero contesto di validazione su ogni oggetto errore, così puoi mappare il tipo di errore più il percorso sul testo che usa il tuo design system.

Articoli correlati

Vedi tutti gli articoli