Skip to main content
Composition keywords let you define shared sub-schemas and combine validation rules.

Supported keywords

KeywordWhat it does
$defs / $refDefine and reuse shared sub-schemas
allOfAll subschemas must match
anyOf / oneOfExactly one subschema must match
notThe subschema must not match

Reuse with $defs and $ref

Define shared sub-schemas once, then reference them.
{
  "$defs": {
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "zip": { "type": "string", "pattern": "^[0-9]{5}$" }
      },
      "required": ["street", "city", "zip"],
      "additionalProperties": false
    }
  },
  "type": "object",
  "properties": {
    "billing": { "$ref": "#/$defs/address" },
    "shipping": { "$ref": "#/$defs/address" }
  },
  "required": ["billing", "shipping"],
  "additionalProperties": false
}
$ref support is for local references (for example #/$defs/...).

allOf

Combine constraints that must all apply.
{
  "allOf": [
    {
      "type": "object",
      "properties": { "name": { "type": "string" } },
      "required": ["name"]
    },
    {
      "type": "object",
      "properties": { "email": { "type": "string", "format": "email" } },
      "required": ["email"]
    }
  ]
}
Pydantic example is omitted because there is no direct allOf keyword mapping.

anyOf / oneOf

Both anyOf and oneOf behave the same way: exactly one subschema must match. Use a discriminator field plus const to make branches explicit.
{
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "tool": { "const": "search" },
        "query": { "type": "string", "minLength": 1 }
      },
      "required": ["tool", "query"],
      "additionalProperties": false
    },
    {
      "type": "object",
      "properties": {
        "tool": { "const": "lookup" },
        "id": { "type": "integer" }
      },
      "required": ["tool", "id"],
      "additionalProperties": false
    }
  ]
}

not

Reject values that match a subschema:
JSON Schema
{
  "type": "object",
  "properties": {
    "value": {
      "type": "string",
      "not": { "const": "" }
    }
  },
  "required": ["value"],
  "additionalProperties": false
}
Pydantic and Zod examples are omitted here because there is no direct keyword mapping for JSON Schema not.
This accepts any non-empty string.

Recursive schemas

Recursive local references are supported:
{
  "$defs": {
    "node": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "children": {
          "type": "array",
          "items": { "$ref": "#/$defs/node" },
          "maxItems": 10
        }
      },
      "required": ["name", "children"],
      "additionalProperties": false
    }
  },
  "type": "object",
  "properties": {
    "root": { "$ref": "#/$defs/node" }
  },
  "required": ["root"],
  "additionalProperties": false
}