Bez additionalProperties validace schématu nic nevaliduje
Shrnutí: Úspěšná validace neznamená čistá data. Pydantic standardně ignoruje neznámá pole, Zod je odstraní, Ajv je pustí — vymyšlené parametry a překlepy projdou potichu. Článek ukazuje tři formy tiché acceptance a dává kompletní recepty: zavřít objekty, zkontrolovat koerci, dotáhnout každou úroveň zanoření.

Závěr: standardně validátory neznámá pole ignorují, místo aby je odmítaly. Bez additionalProperties: false úspěšná validace dokazuje jen to, že deklarovaná pole jsou v pořádku.
Nejnebezpečnější chování validátoru není vyvolat chybu, ale mlčet. Překlep v klíči nebo parametr vymyšlený modelem projde validací neslyšně a vybuchne až v obchodní logice.
Jedna: validace, která „projde"
{
"type": "object",
"properties": {
"order_id": { "type": "string" },
"amount": { "type": "number" }
},
"required": ["order_id", "amount"]
}
Pošlete {"order_id": "A1", "amount": 50, "reasn_code": "damaged"} — třetí klíč je překlep. S výchozí konfigurací Ajv je výsledek úspěch. Nadbytečné pole není ani odmítnuto, ani označeno.
Ve specifikaci JSON Schema je výchozí hodnota additionalProperties true: nedeklarovaná pole jsou povolena.
Dva: tři podoby ticha
| Runtime | Výchozí chování | Důsledek |
|---|---|---|
| Ajv (JS) | pustí | špinavá data dorazí do logiky |
Zod z.object |
odstraní | pole zmizí, objekt se zkrátí |
| Pydantic v2 | ignoruje (extra="ignore") |
totéž, bez stopy v logách |
Odstranění je utajenější než propuštění. Obě knihovny standardně selžou stejně — potichu.
Tři: volání nástrojů LLM problém zesilují
Argumenty generuje model: vymýšlí názvy polí a posílá "3" místo čísla. Platformy definují parametry přes JSON Schema, ale standardně nenutí schéma být uzavřené — strict režim je třeba zapnout explicitně a gramatická omezení pokrývají jen přímý výstup modelu.
{
"order_id": 4411,
"refund_amount_usd": 50,
"reason_code": "damaged",
"urgent": "yes"
}
Se zavřeným objektem jsou reason_code a urgent odmítnuty a chyba ukazuje na /reason_code.
Čtyři: jak zavřít
Ajv: přidejte additionalProperties: false na uzel objektu.
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 nebo .strict(). Pydantic: ConfigDict(extra="forbid").
Společné pravidlo: zavírání probíhá po úrovních. Každý vnořený objekt potřebuje vlastní additionalProperties: false.
Pět: politika koerce
Lax režim Pydanticu převede "5" na 5. Tři politiky: striktní (odmítnout špatné typy), kontrolovaná (jen explicitní omezené konverze), volná (jen interní data). Pro nedůvěryhodné vstupy volte první nebo druhou a zapište ji do testů.
Šest: checklist zanoření
| Bod | Akce |
|---|---|
| Kořenový objekt | additionalProperties: false |
| Každý vnořený objekt | totéž |
| Prvky polí | zavřít objekty v items |
| Enumy a rozsahy | doplnit enum, minimum/maximum |
| Generovaná schémata | doplnit ručně |
Sedm: po odmítnutí
allErrors: true hlásí všechna pole najednou; verbose: true přidá cesty. Syntaktické problémy chytí parser před validací schématu.
FAQ
Není to příliš přísné?
Záleží na kontraktu. U vlastních vstupů zavírejte; u rozšiřitelných dat třetích stran zavřete jen jádro a vyznačte oblast rozšíření.
Strip v Zodu není bezpečnější?
Není: chrání downstream na úkor volajícího. Chyby se mají objevit brzy a explicitně.
Nahrazuje strict režim platformy lokální validaci?
Ne. Samotné schéma může být otevřené a gramatika nemusí pokrývat argumenty nástrojů.
Po zavření hromadně padají stará data?
To je přesně to, co mělo být odhaleno. Zinventarizujte přes allErrors, přidejte neškodná pole, opravte škodlivá.
Řešení na jeden řádek?
Ne, ale minimální krok: ověřit, že za každým type: "object" následuje additionalProperties: false.