JSON Toolkit

Senza additionalProperties, la validazione dello schema non valida nulla

In sintesi: Una validazione superata non significa dati puliti. Pydantic ignora i campi sconosciuti per impostazione predefinita, Zod li rimuove, Ajv li lascia passare — parametri allucinati e chiavi sbagliate attraversano in silenzio. L'articolo mostra le tre forme di accettazione silenziosa e fornisce ricette complete: chiudere gli oggetti, controllare la coercizione, serrare ogni livello di annidamento.

Intermediate~8 min di letturaPubblicato il 2026-11-02Aggiornato il 2026-11-02
Un JSON con campi extra che supera la validazione

Conclusione: per impostazione predefinita i validatori ignorano i campi non dichiarati invece di rifiutarli. Senza additionalProperties: false, una validazione superata prova solo che i campi dichiarati vanno bene.

Il comportamento più pericoloso di un validatore non è sollevare un errore, ma tacere. Una chiave sbagliata o un parametro inventato dal modello attraversa la validazione senza un suono ed esplode nella logica di business.

Uno: una validazione che "passa"

{
  "type": "object",
  "properties": {
    "order_id": { "type": "string" },
    "amount": { "type": "number" }
  },
  "required": ["order_id", "amount"]
}

Inviare {"order_id": "A1", "amount": 50, "reasn_code": "damaged"} — la terza chiave è un errore di battitura. Con la configurazione predefinita di Ajv il risultato è successo. Il campo extra non viene né rifiutato né segnalato.

Nella specifica JSON Schema il valore predefinito di additionalProperties è true: i campi non dichiarati sono ammessi.

Due: tre varianti del silenzio

Runtime Comportamento predefinito Consequenza
Ajv (JS) lascia passare dati sporchi raggiungono la logica
Zod z.object rimuove il campo sparisce, l'oggetto si accorcia
Pydantic v2 ignora (extra="ignore") idem, nessuna traccia nei log

La rimozione è più furtiva del passaggio. Entrambe le librerie falliscono silenziosamente allo stesso modo, per impostazione predefinita.

Tre: le chiamate di strumenti LLM amplificano il problema

Gli argomenti sono generati dal modello, che inventa nomi di campi e passa "3" come numero. Le piattaforme definiscono i parametri in JSON Schema ma non forzano la chiusura dello schema — la modalità strict va attivata esplicitamente, e i vincoli grammaticali coprono solo l'output diretto del modello.

{
  "order_id": 4411,
  "refund_amount_usd": 50,
  "reason_code": "damaged",
  "urgent": "yes"
}

Con l'oggetto chiuso, reason_code e urgent vengono rifiutati e l'errore punta a /reason_code.

Quattro: come chiudere

Ajv: aggiungere additionalProperties: false sul nodo dell'oggetto.

import Ajv from "ajv";
const ajv = new Ajv({ allErrors: true });

const schema = {
  type: "object",
  properties: { order_id: { type: "string" }, amount: { type: "number" } },
  required: ["order_id", "amount"],
  additionalProperties: false,
};

const validate = ajv.compile(schema);
validate({ order_id: "A1", amount: 50, reasn_code: "x" }); // false

Zod: z.strictObject o .strict(). Pydantic: ConfigDict(extra="forbid").

Regola comune: la chiusura è per livello. Ogni oggetto annidato richiede il proprio additionalProperties: false.

Cinque: politica di coercizione

La modalità lax di Pydantic converte "5" in 5. Tre politiche: stretta (rifiutare i tipi errati), controllata (solo conversioni esplicite e limitate), permissiva (solo dati interni). Per input non affidabili scegliere la prima o la seconda e codificarla nei test.

Sei: checklist di annidamento

Punto Azione
Oggetto radice additionalProperties: false
Ogni oggetto annidato idem
Elementi di array chiudere gli oggetti in items
Enum e intervalli aggiungere enum, minimum/maximum
Schemi generati completare a mano

Sette: dopo il rifiuto

allErrors: true segnala tutti i campi insieme; verbose: true aggiunge i percorsi. I problemi di sintassi li cattura il parser prima della validazione dello schema.

FAQ

Troppo severo?

Dipende dal contratto. Per input propri, chiudere; per dati di terzi estensibili, chiudere il nucleo e isolare l'area di estensione.

Lo strip di Zod non è più sicuro?

No: protegge il downstream a spese del chiamante. Gli errori devono emergere presto ed esplicitamente.

La modalità strict della piattaforma sostituisce la validazione locale?

No. Lo schema può restare aperto e la grammatica può non coprire gli argomenti degli strumenti.

I vecchi dati falliscono in massa dopo la chiusura?

È esattamente ciò che andava esposto. Inventariare con allErrors, aggiungere i campi innocui, correggere gli altri.

Una soluzione in una riga?

No, ma il gesto minimo: verificare che ogni type: "object" sia seguito da additionalProperties: false.