json-validator.de

Ratgeber · JSON Schema 2020-12

JSON-Schema-Basics: type, properties und required richtig nutzen

type definiert primitive Typen. properties beschreibt Objekt-Felder. required listet Pflichtfelder. additionalProperties muss explizit gesetzt werden.

Foto von Mateusz Viola

Von Mateusz Viola

Betreiber & redaktionelle Verantwortung json-validator.de

Die drei zentralen Object-Keywords

JSON-Objekte werden mit drei Keywords beschrieben: type, properties, required. Diese Kombination deckt 80 % aller praktischen Use-Cases ab.

type

type legt den Datentyp fest. Werte: "string", "number", "integer", "boolean", "object", "array", "null". Auch ein Array möglicher Typen ist erlaubt:

{ "type": "string" }              // muss String sein
{ "type": ["string", "null"] }    // String oder null (nullable)
{ "type": "integer" }             // Ganzzahl, nicht 3.14

Wichtige Unterscheidung: "integer" ist ein eigener Typ, nicht ein Subset von "number". Wenn beide passen sollen: "type": ["number", "integer"] - aber das ist redundant, da integer ⊂ number gilt.

properties

properties ist die Beschreibung der Felder eines Objekts. Keys sind die Feldnamen, Values sind selbst Sub-Schemas:

{
  "type": "object",
  "properties": {
    "name": { "type": "string", "minLength": 1 },
    "age":  { "type": "integer", "minimum": 0 }
  }
}

Wichtig: properties macht keine Felder zur Pflicht. Wenn properties nur eine Erwartung definiert, ist das Objekt {} ohne Felder erst mal valide.

required

required ist ein Array von Strings - KEIN Objekt. Stehen Feldnamen darin, müssen sie im validierten Objekt vorhanden sein:

{
  "type": "object",
  "required": ["name", "email"],
  "properties": {
    "name":  { "type": "string" },
    "email": { "type": "string", "format": "email" }
  }
}

Typischer Anfänger-Fehler:

// FALSCH
{ "required": { "name": true } }

// RICHTIG
{ "required": ["name"] }

additionalProperties - die unterschätzte vierte Säule

Per Default sind Felder die NICHT in properties stehen, erlaubt. Das ist meist nicht gewollt - Tippfehler im Client werden so still durchgewunken.

{
  "type": "object",
  "required": ["email"],
  "properties": {
    "email": { "type": "string", "format": "email" }
  },
  "additionalProperties": false
}

Damit wirft { "emial": "test@example.com" } einen klaren Validation-Error: "must NOT have additional property 'emial'".

patternProperties - für dynamische Keys

Wenn die Keys eines Objekts nicht statisch sind (z.B. ein Map-Typ):

{
  "type": "object",
  "patternProperties": {
    "^[A-Z]{2}$": {
      "type": "number",
      "minimum": 0,
      "maximum": 1
    }
  },
  "additionalProperties": false
}

Damit passt jedes Objekt wo alle Keys zwei Großbuchstaben sind und alle Werte Zahlen zwischen 0 und 1 (z.B. Wahrscheinlichkeits-Map pro Länder-Code).

minProperties / maxProperties

Begrenzt die Anzahl der Felder im Objekt:

{ "type": "object", "minProperties": 1, "maxProperties": 10 }

Selten direkt nützlich, aber bei dynamischen Maps relevant.

Anti-Pattern: alles in einem Riesen-Schema

Wenn du dein Schema-File auf 800+ Zeilen hast, ist es Zeit für $defs und $ref. Lokale Wiederverwendung:

{
  "$defs": {
    "Address": {
      "type": "object",
      "required": ["street", "city"],
      "properties": {
        "street": { "type": "string" },
        "city":   { "type": "string" }
      }
    }
  },
  "type": "object",
  "properties": {
    "billing":  { "$ref": "#/$defs/Address" },
    "shipping": { "$ref": "#/$defs/Address" }
  }
}

Schema testen

Im Validator oben kannst du dein Schema einsetzen, ein Test-Payload danebenstellen und sofort sehen welche Constraints verletzt werden. Mehrere Iterationen gehen schnell - schneller als jede TDD-Schleife im Backend-Code.

Mehr zum Thema