Skip to content
RelPrim docsJSON Schema

Validation adapters

JSON Schema

Validate operation results against a JSON Schema with the optional relprim.jsonschema adapter. Draft selection, schema errors, failure reasons and paths.

json_schema_validator turns a JSON Schema into a RelPrim validator. It works wherever a validator does: validation_policy(...), @resilient(validation=...) and .with_validation(...). Schema semantics come from the jsonschema package; RelPrim only translates its results.

Install

pip install "relprim[jsonschema]"

Supported versions are jsonschema>=4.3.0,<5.0.0. import relprim never imports it; only relprim.jsonschema does, and importing that module without the extra raises ModuleNotFoundError with the pip install command.

Usage

from relprim import resilient, validation_policy
from relprim.jsonschema import json_schema_validator

USER_SCHEMA = {
    "type": "object",
    "required": ["id", "name"],
    "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"},
    },
}

user_validator = json_schema_validator(USER_SCHEMA, name="user_response")


@resilient(retries=2, timeout=10, validation=validation_policy(user_validator))
async def fetch_user(user_id: int) -> dict[str, object]:
    return await user_service.fetch(user_id)

name defaults to "json_schema" and must not be blank. It appears in reports and validation events. json_schema_validator(...) returns a JSONSchemaValidator.

The validator can also be called directly:

result = user_validator.validate({"id": 1})

result.valid    # False
result.reason   # "'name' is a required property (path: $)"

Schema drafts

The draft is selected from the schema’s $schema keyword using jsonschema’s own validator discovery. Schemas without $schema use the latest draft supported by the installed jsonschema version.

json_schema_validator({"$schema": "http://json-schema.org/draft-07/schema#", "type": "object"})

Invalid schemas

The schema is checked against its metaschema when the validator is created. An invalid schema raises jsonschema.exceptions.SchemaError immediately, unwrapped, so configuration mistakes never surface as invalid operation results:

json_schema_validator({"type": "not-a-real-type"})  # raises SchemaError

Validation failures

A value that does not match returns a failed ValidationResult, and RelPrim raises ValidationFailedError for that attempt. The reason combines jsonschema’s message with the location of the invalid value:

'name' is a required property (path: $)
123 is not of type 'string' (path: $.name)
7 is not of type 'string' (path: $.user.tags[1])

Paths start at $, the whole value; properties are written as .name and array indexes as [1]. When a value has several errors, the single most relevant one selected by jsonschema.exceptions.best_match is reported, deterministically for the same schema and value. Reasons longer than 200 characters are truncated.

Retries and fallbacks

Schema failures are ordinary ValidationFailedError failures, so the usual validation rules apply: they are retried when they match retry_on, and fallback results are validated with the same policy. A fallback can therefore recover from a primary result that failed the schema:

from relprim import ValidationFailedError, resilient, validation_policy


@resilient(
    retries=2,
    retry_on=(ValidationFailedError,),
    fallback=fetch_user_from_replica,
    validation=validation_policy(json_schema_validator(USER_SCHEMA)),
)
async def fetch_user(user_id: int) -> dict[str, object]:
    return await user_service.fetch(user_id)

Limits

  • Values are validated as they are. They are never converted, mutated or filled with schema defaults.
  • Only the most relevant error is reported.
  • format is an annotation, following jsonschema’s default; format assertions are not enabled.
  • RelPrim does not configure remote $ref resolution.
  • Values that are not JSON-compatible, such as dataclass instances, fail the schema’s type checks instead of raising.

The validator accepts values of any type, so validation_policy(json_schema_validator(...)) is a ValidationPolicy[object] and type-checks with operations of any return type.