Skip to content

Latest commit

 

History

History
409 lines (322 loc) · 13.4 KB

File metadata and controls

409 lines (322 loc) · 13.4 KB

Schema validation

The simplest way to validate an instance under OAS schema is to use the validate function.

Validate

validate call signature is:

validate(
    instance,
    schema,
    cls=OAS32Validator,
    allow_remote_references=False,
    check_schema=True,
    enforce_properties_required=False,
    **kwargs,
)

The first argument is always the value you want to validate. The second argument is always the OpenAPI schema object. The cls keyword argument is optional and defaults to OAS32Validator. Use cls when you need a specific validator version/behavior. The allow_remote_references keyword argument is optional and defaults to False. The check_schema keyword argument is optional and defaults to True. Common forwarded keyword arguments include:

  • registry for explicit external reference resolution context
  • format_checker to control format validation behavior

By default, validate uses a local-only empty registry to avoid implicit remote $ref retrieval. Set allow_remote_references=True only if you explicitly accept jsonschema's default remote retrieval behavior.

For trusted pre-validated schemas in hot paths, set check_schema=False to skip schema checking.

When enforce_properties_required=True is passed, all properties declared in the schema's properties object are strictly required to be present in the instance (except those marked as writeOnly or readOnly where appropriate), regardless of the schema's required array. This is useful for response or contract testing to ensure no documented fields are missing.

The shortcut keeps an internal compiled-validator cache. Use OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE to control cache capacity (default: 128). The setting is read once at first use and then cached for the process lifetime.

To validate an OpenAPI schema:

from openapi_schema_validator import validate

# A sample schema
schema = {
    "type": "object",
    "required": [
       "name"
    ],
    "properties": {
        "name": {
            "type": "string"
        },
        "age": {
            "type": ["integer", "null"],
            "format": "int32",
            "minimum": 0,
        },
        "birth-date": {
            "type": "string",
            "format": "date",
        },
        "address": {
             "type": 'array',
             "prefixItems": [
                 { "type": "number" },
                 { "type": "string" },
                 { "enum": ["Street", "Avenue", "Boulevard"] },
                 { "enum": ["NW", "NE", "SW", "SE"] }
             ],
             "items": False,
         }
    },
    "additionalProperties": False,
}

# If no exception is raised by validate(), the instance is valid.
validate({"name": "John", "age": 23, "address": [1600, "Pennsylvania", "Avenue"]}, schema)

validate({"name": "John", "city": "London"}, schema)

Traceback (most recent call last):
    ...
ValidationError: Additional properties are not allowed ('city' was unexpected)

By default, the latest OpenAPI schema syntax is expected.

Common pitfalls

  • argument order matters: call validate(instance, schema), not validate(schema, instance)
  • validate does not load files from a path; load your OpenAPI document first and pass the parsed schema mapping
  • validate treats the provided schema as the reference root; local references like #/components/... must exist within that mapping
  • when a schema uses external references (for example urn:...), provide reference context via registry=... as shown in :doc:`references`
  • for schema fragments containing local references (for example, paths/.../responses/.../schema), use a validator built from the full schema root and then validate the fragment via validator.evolve(...)

Validators

if you want to disambiguate the expected schema version, import and use OAS31Validator:

from openapi_schema_validator import OAS31Validator

validate({"name": "John", "age": 23}, schema, cls=OAS31Validator)

For OpenAPI 3.2, use OAS32Validator.

In order to validate OpenAPI 3.0 schema, import and use OAS30Validator instead of OAS31Validator.

from openapi_schema_validator import OAS30Validator

# A sample schema
schema = {
    "type": "object",
    "required": [
       "name"
    ],
    "properties": {
        "name": {
            "type": "string"
        },
        "age": {
            "type": "integer",
            "format": "int32",
            "minimum": 0,
            "nullable": True,
        },
        "birth-date": {
            "type": "string",
            "format": "date",
        }
    },
    "additionalProperties": False,
}

validate({"name": "John", "age": None}, schema, cls=OAS30Validator)

Default dialect resolution

The OpenAPI 3.1 and 3.2 base dialect URIs are registered for jsonschema.validators.validator_for resolution. If your schema declares "$schema": "https://spec.openapis.org/oas/3.1/dialect/base" or "$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17", validator_for resolves directly to OAS31Validator or OAS32Validator without unresolved-metaschema fallback warnings.

from jsonschema.validators import validator_for

from openapi_schema_validator import OAS31Validator
from openapi_schema_validator import OAS32Validator

schema = {
    "$schema": "https://spec.openapis.org/oas/3.1/dialect/base",
    "type": "object",
}
schema32 = {
    "$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17",
    "type": "object",
}
assert validator_for(schema) is OAS31Validator
assert validator_for(schema32) is OAS32Validator

Schema errors vs instance errors

The high-level validate(...) helper checks schema validity before instance validation by default (check_schema=True), following jsonschema.validate(...) behavior. Malformed schema values (for example an invalid regex in pattern) raise SchemaError.

When check_schema=False, schema checking is skipped and malformed schemas may instead fail during validation with lower-level errors.

If you instantiate a validator class directly and call .validate(...), schema checking is not performed automatically, matching jsonschema validator-class behavior. For malformed regex patterns this may raise a lower-level regex error (default mode) or ValidationError from the validator (ECMAScript mode).

Use <ValidatorClass>.check_schema(schema) first when you need deterministic schema-validation errors with direct validator usage.

Read/write context

OpenAPI 3.0 schema comes with readOnly and writeOnly keywords. In order to validate read/write context in OpenAPI 3.0 schema, import and use OAS30ReadValidator or OAS30WriteValidator.

from openapi_schema_validator import OAS30WriteValidator

# A sample schema
schema = {
    "type": "object",
    "required": [
       "name"
    ],
    "properties": {
        "name": {
            "type": "string"
        },
        "age": {
            "type": "integer",
            "format": "int32",
            "minimum": 0,
            "readOnly": True,
        },
        "birth-date": {
            "type": "string",
            "format": "date",
        }
    },
    "additionalProperties": False,
}

validate({"name": "John", "age": 23}, schema, cls=OAS30WriteValidator)

Traceback (most recent call last):
    ...
ValidationError: Tried to write read-only property with 23

Binary Data Semantics

The handling of binary-like payloads differs between OpenAPI versions.

OpenAPI 3.0

OpenAPI 3.0 keeps historical format: binary / format: byte usage on type: string.

OAS30Validator (default - compatibility behavior)

  • type: string accepts str
  • type: string, format: binary accepts Python bytes and strings
  • maxLength / minLength constrain raw bytes by octet count
  • useful when validating Python-native runtime data

OAS30StrictValidator

  • type: string accepts str only
  • type: string, format: binary uses strict format validation and rejects bytes
  • use when you want strict, spec-oriented behavior for 3.0 schemas

OpenAPI 3.1+

Under JSON Schema 2020-12, OpenAPI 3.1 and 3.2 model raw binary with a typeless schema; the 3.0 format: binary / format: byte pair was dropped. This library accepts Python bytes for raw-binary schemas.

OAS31Validator / OAS32Validator (default - runtime-friendly behavior)

  • the canonical raw-binary form is a typeless schema, optionally annotated with a non-text contentMediaType and no contentEncoding (for example {} or {"contentMediaType": "application/octet-stream"}); a bytes instance validates
  • as a pragmatic compatibility extension, type: string together with a non-text contentMediaType (and no contentEncoding) also accepts bytes -- runtime tolerance for specs migrated from 3.0, not a claim of spec conformance
  • plain type: string accepts str only (not bytes)
  • encoded text stays on the string path: model base64-in-JSON and similar with contentEncoding. Any real contentEncoding (base64, base64url, base16, base32, quoted-printable ...) keeps the schema textual; only the no-op identity encodings (identity / binary / 7bit / 8bit) leave it raw
  • maxLength / minLength constrain raw bytes by octet count

OAS31StrictValidator / OAS32StrictValidator

  • explicit opt-ins that preserve JSON Schema string typing
  • canonical typeless raw binary still accepts bytes
  • a schema asserting type: string rejects bytes even with a non-text contentMediaType (no pragmatic tolerance)
  • validator_for keeps resolving the 3.1 / 3.2 dialect ids to the default validators; the strict classes are never the dialect default

Note

Migration from 3.0: in 3.1 / 3.2 format: binary is no longer a binary marker (under 2020-12 format is an annotation). A bytes value validated against a 3.1 / 3.2 {"type": "string", "format": "binary"} schema is now rejected -- model raw binary with contentMediaType (ideally a typeless schema) instead.

Quick Reference

Context "text" (str) b"text" (bytes) Notes
OAS 3.0 + OAS30Validator Pass Pass for format: binary Compatibility behavior for Python runtime payloads
OAS 3.0 + OAS30StrictValidator Pass Fail Strict 3.0 validation mode
OAS 3.1 + OAS31Validator Pass Pass for raw binary Typeless, or type: string + non-text contentMediaType
OAS 3.2 + OAS32Validator Pass Pass for raw binary Same semantics as OAS 3.1
OAS 3.1/3.2 strict validators Pass Pass for typeless raw binary Rejects bytes whenever type: string is asserted

Example usage:

from openapi_schema_validator import OAS31StrictValidator
from openapi_schema_validator import OAS31Validator

# Canonical typeless raw binary - accepts bytes
validator = OAS31Validator({"contentMediaType": "application/octet-stream"})
validator.validate(b"binary data")  # passes

# Pragmatic compatibility extension (default validators only)
validator = OAS31Validator(
    {"type": "string", "contentMediaType": "application/octet-stream"}
)
validator.validate(b"binary data")  # passes

# Octet-length bounds apply to raw bytes
validator = OAS31Validator(
    {"contentMediaType": "application/pdf", "maxLength": 1}
)
validator.validate(b"abc")  # raises ValidationError (3 octets > 1)

# Strict - preserves JSON Schema string typing
validator = OAS31StrictValidator(
    {"type": "string", "contentMediaType": "application/octet-stream"}
)
validator.validate(b"binary data")  # raises ValidationError

Regex Behavior

Pattern validation follows one of two modes:

  • default installation: follows host Python regex behavior
  • ecma-regex extra installed: uses regress for ECMAScript-oriented regex validation and matching

Install optional ECMAScript regex support with:

pip install "openapi-schema-validator[ecma-regex]"

Example usage:

from openapi_schema_validator import OAS30StrictValidator
from openapi_schema_validator import OAS30Validator

# Pragmatic (default) - accepts bytes for binary format
validator = OAS30Validator({"type": "string", "format": "binary"})
validator.validate(b"binary data")  # passes

# Strict - follows spec precisely
validator = OAS30StrictValidator({"type": "string", "format": "binary"})
validator.validate(b"binary data")  # raises ValidationError