Ohne additionalProperties validiert das Schema nichts
Fazit: Eine bestandene Validierung bedeutet keine sauberen Daten. Pydantic ignoriert unbekannte Felder standardmäßig, Zod entfernt sie, Ajv lässt sie durch — erfundene Parameter und Tippfehler-Schlüssel rutschen lautlos durch. Dieser Artikel zeigt die drei Formen stiller Akzeptanz und liefert vollständige Rezepte: Objekte schließen, Typos-Konvertierung kontrollieren, jede Verschachtelungsebene festziehen.

Fazit: Standardmäßig ignorieren Validatoren nicht deklarierte Felder, statt sie abzulehnen. Ohne additionalProperties: false beweist eine bestandene Validierung nur, dass die deklarierten Felder in Ordnung sind.
Das gefährlichste Verhalten eines Validators ist nicht der Fehler, sondern die Stille. Ein Tippfehler-Schlüssel oder ein vom Modell erfundener Parameter rutscht lautlos durch die Validierung und explodiert erst in der Geschäftslogik.
Eins: eine Validierung, die „besteht"
{
"type": "object",
"properties": {
"order_id": { "type": "string" },
"amount": { "type": "number" }
},
"required": ["order_id", "amount"]
}
Übergibt man {"order_id": "A1", "amount": 50, "reasn_code": "damaged"} — der dritte Schlüssel ist ein Tippfehler —, ist das Ergebnis mit Ajvs Standardeinstellung ein Erfolg. Das überzählige Feld wird weder abgelehnt noch gemeldet.
In der JSON-Schema-Spezifikation ist der Standardwert von additionalProperties true: nicht deklarierte Felder sind erlaubt.
Zwei: drei Spielarten der Stille
| Laufzeit | Standardverhalten | Folge |
|---|---|---|
| Ajv (JS) | lässt durch | schmutzige Daten erreichen die Logik |
Zod z.object |
entfernt | Feld verschwindet, Objekt wird kürzer |
| Pydantic v2 | ignoriert (extra="ignore") |
dito, keine Spur in den Logs |
Entfernen ist heimlicher als Durchlassen. Beide Bibliotheken schlagen standardmäßig auf dieselbe Weise fehl — still.
Drei: LLM-Toolaufrufe verschärfen das Problem
Tool-Argumente erzeugt das Modell: es erfindet Feldnamen und übergibt "3" als Zahl. Plattformen definieren Parameter als JSON-Schema, erzwingen aber standardmäßig kein geschlossenes Schema — der Strict-Modus muss explizit aktiviert werden, und Grammatikregeln gelten nur für die direkte Modellausgabe.
{
"order_id": 4411,
"refund_amount_usd": 50,
"reason_code": "damaged",
"urgent": "yes"
}
Mit geschlossenem Objekt werden reason_code und urgent abgelehnt, und der Fehler zeigt auf /reason_code.
Vier: So wird geschlossen
Ajv: additionalProperties: false am Objektknoten ergänzen.
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 oder .strict(). Pydantic: ConfigDict(extra="forbid").
Gemeinsame Regel: Das Schließen erfolgt pro Ebene. Jedes verschachtelte Objekt braucht sein eigenes additionalProperties: false.
Fünf: die Konvertierungsrichtlinie
Pydantics Lax-Modus macht aus "5" eine 5. Drei Richtlinien: strikt (falsche Typen ablehnen), kontrolliert (nur explizite, begrenzte Konvertierungen), frei (nur für interne Daten). Für nicht vertrauenswürdige Eingaben die erste oder zweite wählen und in Tests festhalten.
Sechs: Checkliste für Verschachtelung
| Punkt | Maßnahme |
|---|---|
| Top-Level-Objekt | additionalProperties: false |
| Jedes verschachtelte Objekt | ebenso |
| Array-Elemente | Objekte in items schließen |
| Enums und Bereiche | enum, minimum/maximum ergänzen |
| Generierte Schemas | von Hand vervollständigen |
Sieben: nach der Ablehnung
allErrors: true meldet alle Felder auf einmal, verbose: true liefert Pfade. Syntaxprobleme fängt der Parser vor der Schema-Validierung.
FAQ
Zu streng?
Kommt auf den Vertrag an. Eigene Eingaben: schließen. Erweiterbare Fremddaten: nur den Kern schließen und den Erweiterungsbereich markieren.
Zods Strip ist sicherer?
Nein: Er schützt das Downstream auf Kosten des Aufrufers. Fehler müssen früh und explizit auftreten.
Ersetzt der Strict-Modus der Plattform die lokale Validierung?
Nein. Das Schema selbst kann offen sein, und die Grammatik deckt Tool-Argumente nicht ab.
Altdaten fallen massenhaft durch?
Genau das sollte sichtbar werden. Mit allErrors inventarisieren, harmlose Felder ergänzen, schädliche korrigieren.
Eine Einzeilen-Lösung?
Nein, aber ein Mindestschritt: prüfen, dass jedem type: "object" ein additionalProperties: false folgt.