jsonschema-rs 0.58.1


pip install jsonschema-rs

  Latest version

Released: Sep 26, 2026


Meta
Author: Dmitry Dygalo
Maintainer: Dmitry Dygalo
Requires Python: >=3.10

Classifiers

Development Status
  • 4 - Beta

Intended Audience
  • Developers

License
  • OSI Approved :: MIT License

Operating System
  • OS Independent

Programming Language
  • Python :: 3
  • Python :: 3 :: Only
  • Python :: 3.10
  • Python :: 3.11
  • Python :: 3.12
  • Python :: 3.13
  • Python :: 3.14
  • Python :: 3.15
  • Python :: Implementation :: CPython
  • Python :: Implementation :: PyPy
  • Rust

Topic
  • File Formats :: JSON :: JSON Schema

jsonschema-rs

Build Version Python versions License Supported Dialects

A high-performance JSON Schema validator for Python.

import jsonschema_rs

schema = {"maxLength": 5}
instance = "foo"

# One-off validation
try:
    jsonschema_rs.validate(schema, "incorrect")
except jsonschema_rs.ValidationError as exc:
    assert str(exc) == '''"incorrect" is longer than 5 characters

Failed validating "maxLength" in schema

On instance:
    "incorrect"'''

# Build & reuse (faster)
validator = jsonschema_rs.validator_for(schema)

# Iterate over errors
for error in validator.iter_errors(instance):
    print(f"Error: {error}")
    print(f"Location: {error.instance_path}")

# Boolean result
assert validator.is_valid(instance)

# Structured output (JSON Schema Output v1)
evaluation = validator.evaluate(instance)
for error in evaluation.errors():
    print(f"Error at {error['instanceLocation']}: {error['error']}")

โš ๏ธ Upgrading from older versions? Check our Migration Guide for key changes.

Migrating from jsonschema? See the jsonschema migration guide.

Highlights

  • ๐Ÿ“š Full support for popular JSON Schema drafts
  • ๐ŸŒ Remote reference fetching (network/file)
  • ๐Ÿ”ง Custom keywords and format validators
  • โœจ Meta-schema validation for schema documents
  • ๐Ÿ“ฆ Schema bundling into Compound Schema Documents, and $ref dereferencing
  • ๐Ÿงฎ Experimental schema canonicalization

Supported drafts

The following drafts are supported:

  • Draft 2020-12
  • Draft 2019-09
  • Draft 7
  • Draft 6
  • Draft 4

You can check the current status on the Bowtie Report.

Playground

If you'd like to try jsonschema, you can check the WebAssembly-powered playground to see the results instantly.

Installation

To install jsonschema-rs via pip run the following command:

pip install jsonschema-rs

Usage

If you have a schema as a JSON string, then you could pass it to validator_for to avoid parsing on the Python side:

import jsonschema_rs

validator = jsonschema_rs.validator_for('{"minimum": 42}')
...

You can use draft-specific validators for different JSON Schema versions:

import jsonschema_rs

# Automatic draft detection
validator = jsonschema_rs.validator_for({"minimum": 42})

# Draft-specific validators
validator = jsonschema_rs.Draft7Validator({"minimum": 42})
validator = jsonschema_rs.Draft201909Validator({"minimum": 42})
validator = jsonschema_rs.Draft202012Validator({"minimum": 42})

JSON Schema allows for format validation through the format keyword. While jsonschema-rs provides built-in validators for standard formats, you can also define custom format validators for domain-specific string formats.

To implement a custom format validator:

  1. Define a function that takes a str and returns a bool.
  2. Pass it with the formats argument.
  3. Ensure validate_formats is set appropriately (especially for Draft 2019-09 and 2020-12).
import jsonschema_rs

def is_currency(value):
    # The input value is always a string
    return len(value) == 3 and value.isascii()


validator = jsonschema_rs.validator_for(
    {"type": "string", "format": "currency"}, 
    formats={"currency": is_currency},
    validate_formats=True  # Important for Draft 2019-09 and 2020-12
)
validator.is_valid("USD")  # True
validator.is_valid("invalid")  # False

Custom Keywords

You can extend JSON Schema with custom keywords for domain-specific validation rules. Custom keywords are classes that receive the keyword value during schema compilation and validate instances at runtime:

import jsonschema_rs

class DivisibleBy:
    def __init__(self, parent_schema, value, schema_path):
        self.divisor = value

    def validate(self, instance):
        if isinstance(instance, int) and instance % self.divisor != 0:
            raise ValueError(f"{instance} is not divisible by {self.divisor}")


validator = jsonschema_rs.validator_for(
    {"type": "integer", "divisibleBy": 3},
    keywords={"divisibleBy": DivisibleBy},
)
validator.is_valid(9)   # True
validator.is_valid(10)  # False

When validate raises, the original exception is preserved as the __cause__ of the ValidationError, so callers can inspect it:

try:
    validator.validate(instance)
except jsonschema_rs.ValidationError as e:
    print(type(e.__cause__))   # <class 'ValueError'>
    print(e.__cause__)         # original message

Additional configuration options are available for fine-tuning the validation process:

  • validate_formats: Override the draft-specific default behavior for format validation.
  • ignore_unknown_formats: Control whether unrecognized formats should be reported as errors.
  • base_uri - a base URI for all relative $ref in the schema.
  • vocabularies: Declare support for vocabularies implemented by custom keywords.

Example usage of these options:

import jsonschema_rs

validator = jsonschema_rs.Draft202012Validator(
    {"type": "string", "format": "date"},
    validate_formats=True,
    ignore_unknown_formats=False
)

# This will validate the "date" format
validator.is_valid("2023-05-17")  # True
validator.is_valid("not a date")  # False

# With ignore_unknown_formats=False, using an unknown format will raise an error
invalid_schema = {"type": "string", "format": "unknown"}
try:
    jsonschema_rs.Draft202012Validator(
        invalid_schema, validate_formats=True, ignore_unknown_formats=False
    )
except jsonschema_rs.ValidationError as exc:
    assert str(exc) == '''Unknown format: 'unknown'. Adjust configuration to ignore unrecognized formats

Failed validating "format" in schema

On instance["format"]:
    "unknown"'''

Structured Output with evaluate

When you need more than a boolean result, use the evaluate API to access the JSON Schema Output v1 formats:

import jsonschema_rs

schema = {
    "type": "array",
    "prefixItems": [{"type": "string"}],
    "items": {"type": "integer"},
}
evaluation = jsonschema_rs.evaluate(schema, ["hello", "oops"])

assert evaluation.flag() == {"valid": False}
assert evaluation.list() == {
    "valid": False,
    "details": [
        {
            "evaluationPath": "",
            "instanceLocation": "",
            "schemaLocation": "",
            "valid": False,
        },
        {
            "valid": True,
            "evaluationPath": "/type",
            "instanceLocation": "",
            "schemaLocation": "/type",
        },
        {
            "valid": False,
            "evaluationPath": "/items",
            "instanceLocation": "",
            "schemaLocation": "/items",
            "droppedAnnotations": True,
        },
        {
            "valid": False,
            "evaluationPath": "/items",
            "instanceLocation": "/1",
            "schemaLocation": "/items",
        },
        {
            "valid": False,
            "evaluationPath": "/items/type",
            "instanceLocation": "/1",
            "schemaLocation": "/items/type",
            "errors": {"type": '"oops" is not of type "integer"'},
        },
        {
            "valid": True,
            "evaluationPath": "/prefixItems",
            "instanceLocation": "",
            "schemaLocation": "/prefixItems",
            "annotations": 0,
        },
        {
            "valid": True,
            "evaluationPath": "/prefixItems/0",
            "instanceLocation": "/0",
            "schemaLocation": "/prefixItems/0",
        },
        {
            "valid": True,
            "evaluationPath": "/prefixItems/0/type",
            "instanceLocation": "/0",
            "schemaLocation": "/prefixItems/0/type",
        },
    ],
}

hierarchical = evaluation.hierarchical()
assert hierarchical == {
    "valid": False,
    "evaluationPath": "",
    "instanceLocation": "",
    "schemaLocation": "",
    "details": [
        {
            "valid": True,
            "evaluationPath": "/type",
            "instanceLocation": "",
            "schemaLocation": "/type",
        },
        {
            "valid": False,
            "evaluationPath": "/items",
            "instanceLocation": "",
            "schemaLocation": "/items",
            "droppedAnnotations": True,
            "details": [
                {
                    "valid": False,
                    "evaluationPath": "/items",
                    "instanceLocation": "/1",
                    "schemaLocation": "/items",
                    "details": [
                        {
                            "valid": False,
                            "evaluationPath": "/items/type",
                            "instanceLocation": "/1",
                            "schemaLocation": "/items/type",
                            "errors": {"type": '"oops" is not of type "integer"'},
                        }
                    ],
                }
            ],
        },
        {
            "valid": True,
            "evaluationPath": "/prefixItems",
            "instanceLocation": "",
            "schemaLocation": "/prefixItems",
            "annotations": 0,
            "details": [
                {
                    "valid": True,
                    "evaluationPath": "/prefixItems/0",
                    "instanceLocation": "/0",
                    "schemaLocation": "/prefixItems/0",
                    "details": [
                        {
                            "valid": True,
                            "evaluationPath": "/prefixItems/0/type",
                            "instanceLocation": "/0",
                            "schemaLocation": "/prefixItems/0/type",
                        }
                    ],
                }
            ],
        },
    ],
}

assert evaluation.errors() == [
    {
        "schemaLocation": "/items/type",
        "absoluteKeywordLocation": None,
        "instanceLocation": "/1",
        "error": '"oops" is not of type "integer"',
    }
]

assert evaluation.annotations() == [
    {
        "schemaLocation": "/prefixItems",
        "absoluteKeywordLocation": None,
        "instanceLocation": "",
        "annotations": 0,
    }
]

Arbitrary-Precision Numbers

The Python bindings always include the arbitrary-precision support from the Rust validator, so numeric values are exposed to Python using the most accurate type available:

  • Integers, regardless of size, are returned as regular int objects.
  • Floating-point literals that fit into IEEE-754 become Python floats.
  • Floating-point literals that don't fit in float (for example 1e10000 or extremely precise decimals) fall back to decimal.Decimal using their original JSON string representation.

This means ValidationError.kind attributes may contain Decimal instances for very large numbers. Import Decimal from the standard library if you need to compare against or serialize those values exactly:

from decimal import Decimal
from jsonschema_rs import ValidationError, validator_for

validator = validator_for('{"const": 1e10000}')
try:
    validator.validate(0)
except ValidationError as exc:
    assert exc.kind.expected_value == Decimal("1e10000")

# Extremely large exponents (beyond ~10^1_000_000) are clamped internally to keep parsing
# predictable, matching the Rust implementation's guardrails.

Schema Bundling and Dereferencing

Produce a Compound Schema Document (Appendix B) by embedding all external $ref targets into a draft-appropriate container. The result validates identically to the original.

import jsonschema_rs

address_schema = {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://example.com/address.json",
    "type": "object",
    "properties": {"street": {"type": "string"}, "city": {"type": "string"}},
    "required": ["street", "city"]
}

schema = {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {"home": {"$ref": "https://example.com/address.json"}},
    "required": ["home"]
}

registry = jsonschema_rs.Registry([("https://example.com/address.json", address_schema)])
bundled = jsonschema_rs.bundle(schema, registry=registry)

dereference instead replaces each $ref with the schema it points to, for consumers that do not resolve references. Circular references are left in place.

dereferenced = jsonschema_rs.dereference(schema, registry=registry)

Schema Canonicalization

Experimental: the canonicalization API may change in minor releases.

canonicalize reduces a schema to a normal form without changing the values it accepts. Schemas that accept the same values reduce to equal CanonicalSchema objects, and contradictions reduce to false:

import jsonschema_rs

canonical = jsonschema_rs.canonicalize({
    "allOf": [{"type": "integer", "minimum": 0}, {"minimum": 10, "maximum": 100}]
})
assert canonical.to_json_schema() == {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "integer", "minimum": 10, "maximum": 100,
}

# However they were written, equivalent schemas compare equal
assert canonical == jsonschema_rs.canonicalize({"type": "integer", "maximum": 100, "minimum": 10})

# A schema no value can satisfy collapses
from jsonschema_rs.canonical import Satisfiability

assert jsonschema_rs.canonicalize({"type": "integer", "minimum": 10, "maximum": 5}).satisfiability() == Satisfiability.NO

A canonical schema is the set of values it accepts, so canonical schemas combine as sets. Every emitted schema carries $schema, left out of the comments below:

positive = jsonschema_rs.canonicalize({"type": "integer", "minimum": 0})
bounded = jsonschema_rs.canonicalize({"type": "integer", "maximum": 100})

# Every value both admit
positive.intersect(bounded).to_json_schema()
# {"type": "integer", "minimum": 0, "maximum": 100}

# Every value either admits
positive.union(bounded).to_json_schema()
# {"type": "integer"}

# Every value `positive` admits and `bounded` rejects
positive.subtract(bounded).to_json_schema()
# {"type": "integer", "minimum": 101}

# Every value `positive` rejects, across the types it never admitted
positive.negate().to_json_schema()
# {"anyOf": [{"type": ["null", "boolean", "string", "array", "object"]},
#            {"type": "integer", "maximum": -1},
#            {"type": "number", "not": {"multipleOf": 1}}]}

positive.covers(bounded)        # Containment.NO - `bounded` takes negative integers, `positive` does not
positive.satisfiability()       # Satisfiability.YES

Comparing two versions of a schema

The difference answers what editing a schema did to the values it takes: it accepts exactly what the old schema took and the new one turns away, and is unsatisfiable exactly when nothing was lost.

old = jsonschema_rs.canonicalize({"type": "string"})
new = jsonschema_rs.canonicalize({"type": "string", "maxLength": 50})

# What `new` stopped accepting, as a schema
assert old.subtract(new).to_json_schema() == {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "string", "minLength": 51,
}
# Nothing is accepted that was not accepted before, so the change only narrows
assert new.subtract(old).satisfiability() == Satisfiability.NO

Compare a request schema new-against-old and a response schema old-against-new: narrowing a request turns away payloads a caller used to send, widening a response returns values a caller never agreed to read.

Satisfiability.NO on the difference proves nothing was lost. UNKNOWN proves nothing either way.

UNKNOWN is undecided, not negative, so the two questions have opposite safe tests: only satisfiability() == Satisfiability.NO proves a schema admits nothing, and only covers() == Containment.YES proves containment.

Containment, Satisfiability, Distinctness, CanonicalKind, UnsatisfiableReason and Cause live in jsonschema_rs.canonical.

Both operands must share one setup - the same draft, format policy, regular-expression engine and definitions - or IncompatibleOperands is raised. UnsupportedOperand means an operand is a Raw pass-through, and UnsupportedResult that the canonical form does not support the result.

Finding the dead subschemas of a document

find_unsatisfiable walks a whole document and answers which of its subschemas admit no value, and why - the keywords at fault and where they sit:

from jsonschema_rs.canonical import UnsatisfiableReason, find_unsatisfiable

reasons = find_unsatisfiable({
    "properties": {
        "tag": {"type": "string", "minLength": 5, "maxLength": 2},
        "name": {"type": "string"},
    }
})

match reasons["/properties/tag"]:
    case UnsatisfiableReason.Conflict(causes):
        assert [(cause.pointer, cause.keywords) for cause in causes] == [
            ("/properties/tag", ["type"]),
            ("/properties/tag", ["minLength", "maxLength"]),
        ]

# A live subschema is not reported
assert "/properties/name" not in reasons

A reason is Literal (written as false), Empty (one part admits nothing by itself) or Conflict (each part admits values, together they admit none). A pointer left out is not proven satisfiable: a document canonicalization cannot model reports nothing, as Satisfiability answers UNKNOWN.

Meta-Schema Validation

JSON Schema documents can be validated against their meta-schemas to ensure they are valid schemas. jsonschema-rs provides this functionality through the meta module:

import jsonschema_rs

# Valid schema
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer", "minimum": 0}
    },
    "required": ["name"]
}

# Validate schema (draft is auto-detected)
assert jsonschema_rs.meta.is_valid(schema)
jsonschema_rs.meta.validate(schema)  # No error raised

# Invalid schema
invalid_schema = {
    "minimum": "not_a_number"  # "minimum" must be a number
}

try:
    jsonschema_rs.meta.validate(invalid_schema)
except jsonschema_rs.ValidationError as exc:
    assert 'is not of type "number"' in str(exc)

Regular Expression Configuration

When validating schemas with regex patterns (in pattern or patternProperties), you can configure the underlying regex engine:

import jsonschema_rs
from jsonschema_rs import FancyRegexOptions, RegexOptions

# Default fancy-regex engine with backtracking limits
# (supports advanced features but needs protection against DoS)
validator = jsonschema_rs.validator_for(
    {"type": "string", "pattern": "^(a+)+$"},
    pattern_options=FancyRegexOptions(backtrack_limit=10_000)
)

# Standard regex engine for guaranteed linear-time matching
# (prevents regex DoS attacks but supports fewer features)
validator = jsonschema_rs.validator_for(
    {"type": "string", "pattern": "^a+$"},
    pattern_options=RegexOptions()
)

# Both engines support memory usage configuration
validator = jsonschema_rs.validator_for(
    {"type": "string", "pattern": "^a+$"},
    pattern_options=RegexOptions(
        size_limit=1024 * 1024,   # Maximum compiled pattern size
        dfa_size_limit=10240      # Maximum DFA cache size
    )
)

The available options:

  • FancyRegexOptions: Default engine with lookaround and backreferences support

    • backtrack_limit: Maximum backtracking steps
    • size_limit: Maximum compiled regex size in bytes
    • dfa_size_limit: Maximum DFA cache size in bytes
  • RegexOptions: Safer engine with linear-time guarantee

    • size_limit: Maximum compiled regex size in bytes
    • dfa_size_limit: Maximum DFA cache size in bytes

This configuration is crucial when working with untrusted schemas where attackers might craft malicious regex patterns.

Email Format Configuration

When validating email addresses using {"format": "email"}, you can customize the validation behavior beyond the default JSON Schema spec requirements:

import jsonschema_rs
from jsonschema_rs import EmailOptions

# Require a top-level domain (reject "user@localhost")
validator = jsonschema_rs.validator_for(
    {"format": "email", "type": "string"},
    validate_formats=True,
    email_options=EmailOptions(require_tld=True)
)
validator.is_valid("user@localhost")     # False
validator.is_valid("user@example.com")   # True

# Disallow IP address literals and display names
validator = jsonschema_rs.validator_for(
    {"format": "email", "type": "string"},
    validate_formats=True,
    email_options=EmailOptions(
        allow_domain_literal=False,  # Reject "user@[127.0.0.1]"
        allow_display_text=False     # Reject "Name <user@example.com>"
    )
)

# Require minimum domain segments
validator = jsonschema_rs.validator_for(
    {"format": "email", "type": "string"},
    validate_formats=True,
    email_options=EmailOptions(minimum_sub_domains=3)  # e.g., user@sub.example.com
)

Available options:

  • require_tld: Require a top-level domain (e.g., reject "user@localhost")
  • allow_domain_literal: Allow IP address literals like "user@[127.0.0.1]" (default: True)
  • allow_display_text: Allow display names like "Name user@example.com" (default: True)
  • minimum_sub_domains: Minimum number of domain segments required

External References

By default, jsonschema-rs resolves HTTP references and file references from the local file system. You can implement a custom retriever to handle external references. Here's an example that uses a static map of schemas:

import jsonschema_rs

def retrieve(uri: str):
    schemas = {
        "https://example.com/person.json": {
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "age": {"type": "integer"}
            },
            "required": ["name", "age"]
        }
    }
    if uri not in schemas:
        raise KeyError(f"Schema not found: {uri}")
    return schemas[uri]

schema = {
    "$ref": "https://example.com/person.json"
}

validator = jsonschema_rs.validator_for(schema, retriever=retrieve)

# This is valid
validator.is_valid({
    "name": "Alice",
    "age": 30
})

# This is invalid (missing "age")
validator.is_valid({
    "name": "Bob"
})  # False

Schema Registry

For applications that frequently use the same schemas, you can create a registry to store and reference them efficiently:

import jsonschema_rs

# Create a registry with schemas
registry = jsonschema_rs.Registry([
    ("https://example.com/address.json", {
        "type": "object",
        "properties": {
            "street": {"type": "string"},
            "city": {"type": "string"}
        }
    }),
    ("https://example.com/person.json", {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "address": {"$ref": "https://example.com/address.json"}
        }
    })
])

# Use the registry with any validator
validator = jsonschema_rs.validator_for(
    {"$ref": "https://example.com/person.json"},
    registry=registry
)

# Validate instances
assert validator.is_valid({
    "name": "John",
    "address": {"street": "Main St", "city": "Boston"}
})

The registry can be configured with a draft version and a retriever for external references:

import jsonschema_rs

registry = jsonschema_rs.Registry(
    resources=[
        (
            "https://example.com/address.json",
            {}
        )
    ],  # Your schemas
    draft=jsonschema_rs.Draft202012,  # Optional
    retriever=lambda uri: {}  # Optional
)

Error Handling

jsonschema-rs provides detailed validation errors through the ValidationError class, which includes both basic error information and specific details about what caused the validation to fail:

import jsonschema_rs

schema = {"type": "string", "maxLength": 5}

try:
    jsonschema_rs.validate(schema, "too long")
except jsonschema_rs.ValidationError as error:
    # Basic error information
    print(error.message)       # '"too long" is longer than 5 characters'
    print(error.instance_path) # Location in the instance that failed
    print(error.schema_path)   # Location in the schema that failed

    # Detailed error information via `kind`
    if isinstance(error.kind, jsonschema_rs.ValidationErrorKind.MaxLength):
        assert error.kind.limit == 5
        print(f"Exceeded maximum length of {error.kind.limit}")

For a complete list of all error kinds and their attributes, see the type definitions file

Error Kind Properties

Each error has a kind property with convenient accessors:

for error in jsonschema_rs.iter_errors({"minimum": 5}, 3):
    print(error.kind.name)      # "minimum"
    print(error.kind.value)     # 5
    print(error.kind.as_dict()) # {"limit": 5}

Pattern matching (Python 3.10+):

for error in jsonschema_rs.iter_errors({"minimum": 5}, 3):
    match error.kind:
        case jsonschema_rs.ValidationErrorKind.Minimum(limit=limit):
            print(f"Value below {limit}")
        case jsonschema_rs.ValidationErrorKind.Type(types=types):
            print(f"Expected one of {types}")

Error Message Masking

When working with sensitive data, you might want to hide actual values from error messages. You can mask instance values in error messages by providing a placeholder:

import jsonschema_rs

schema = {
    "type": "object",
    "properties": {
        "password": {"type": "string", "minLength": 8},
        "api_key": {"type": "string", "pattern": "^[A-Z0-9]{32}$"}
    }
}

# Use default masking (replaces values with "[REDACTED]")
validator = jsonschema_rs.validator_for(schema, mask="[REDACTED]")

try:
    validator.validate({
        "password": "123",
        "api_key": "secret_key_123"
    })
except jsonschema_rs.ValidationError as exc:
    assert str(exc) == '''[REDACTED] is shorter than 8 characters

Failed validating "minLength" in schema["properties"]["password"]

On instance["password"]:
    [REDACTED]'''

Performance

jsonschema-rs is designed for high performance, outperforming other Python JSON Schema validators in most scenarios:

  • 138-10,841x faster than jsonschema for complex schemas and large instances
  • 8-1,848x faster than fastjsonschema on CPython

For detailed benchmarks, see our full performance comparison.

Compile-Time Validators

If you ship your own extension module and know the schema at build time, the Rust crate's #[jsonschema::validator(..., backend = Pyo3)] macro compiles it into a validator that reads Python objects directly, so nothing is parsed or compiled when your module is imported, and validation runs up to 4.8x faster than with a validator built at run time. See the macro documentation.

This is not available from the jsonschema-rs package on PyPI, which takes its schemas at run time. A complete extension with its build and test commands lives in examples/pyo3-extension.

Python support

jsonschema-rs supports CPython 3.10 through 3.14 and PyPy 3.10+.

Pre-built wheels are available for:

  • Linux: x86_64, i686, aarch64 (glibc and musl)
  • macOS: x86_64, aarch64, universal2
  • Windows: x64, x86, arm64

Troubleshooting

If you encounter linking errors when building from source on Linux (e.g., undefined symbol errors related to ring or crypto), try using the mold linker:

RUSTFLAGS="-C link-arg=-fuse-ld=mold" pip install jsonschema-rs --no-binary :all:

Acknowledgements

This library draws API design inspiration from the Python jsonschema package. We're grateful to the Python jsonschema maintainers and contributors for their pioneering work in JSON Schema validation.

Support

If you have questions, need help, or want to suggest improvements, please use GitHub Discussions.

Sponsorship

If you find jsonschema-rs useful, please consider sponsoring its development.

Contributing

We welcome contributions! Here's how you can help:

See CONTRIBUTING.md for more details.

License

Licensed under MIT License.

0.58.1 Sep 26, 2026
0.58.0 Sep 25, 2026
0.57.1 Sep 21, 2026
0.56.0 Sep 10, 2026
0.55.1 Sep 08, 2026
0.55.0 Sep 06, 2026
0.54.0 Sep 06, 2026
0.53.0 Sep 02, 2026
0.52.1 Aug 30, 2026
0.52.0 Aug 26, 2026
0.51.0 Aug 23, 2026
0.50.1 Aug 22, 2026
0.50.0 Aug 20, 2026
0.49.9 Aug 09, 2026
0.49.8 Aug 08, 2026
0.49.7 Aug 07, 2026
0.49.6 Aug 06, 2026
0.49.5 Aug 04, 2026
0.49.4 Aug 03, 2026
0.49.3 Aug 02, 2026
0.49.2 Jul 27, 2026
0.49.1 Jul 25, 2026
0.49.0 Jul 25, 2026
0.48.5 Jul 22, 2026
0.48.2 Jul 20, 2026
0.48.1 Jul 17, 2026
0.48.0 Jul 16, 2026
0.47.0 Jul 07, 2026
0.46.10 Jul 05, 2026
0.46.9 Jul 02, 2026
0.46.8 Jul 01, 2026
0.46.7 Jun 30, 2026
0.46.6 Jun 23, 2026
0.46.5 May 13, 2026
0.46.4 May 01, 2026
0.46.3 Apr 28, 2026
0.46.2 Apr 20, 2026
0.46.1 Apr 18, 2026
0.46.0 Apr 10, 2026
0.45.1 Apr 06, 2026
0.45.0 Mar 08, 2026
0.44.1 Mar 03, 2026
0.44.0 Mar 01, 2026
0.43.0 Feb 28, 2026
0.42.2 Feb 26, 2026
0.42.1 Feb 17, 2026
0.42.0 Feb 14, 2026
0.41.0 Feb 04, 2026
0.40.4 Jan 31, 2026
0.40.3 Jan 30, 2026
0.40.2 Jan 30, 2026
0.40.1 Jan 29, 2026
0.40.0 Jan 18, 2026
0.39.0 Jan 16, 2026
0.38.1 Dec 24, 2025
0.38.0 Dec 24, 2025
0.37.4 Nov 30, 2025
0.37.3 Nov 28, 2025
0.37.2 Nov 27, 2025
0.37.1 Nov 19, 2025
0.37.0 Nov 19, 2025
0.36.0 Nov 18, 2025
0.35.0 Nov 16, 2025
0.34.0 Nov 14, 2025
0.33.0 Aug 24, 2025
0.32.1 Aug 03, 2025
0.32.0 Jul 29, 2025
0.31.0 Jul 27, 2025
0.30.0 Apr 16, 2025
0.29.1 Feb 08, 2025
0.29.0 Feb 08, 2025
0.28.3 Jan 24, 2025
0.28.2 Jan 22, 2025
0.28.1 Dec 31, 2024
0.28.0 Dec 29, 2024
0.27.1 Dec 24, 2024
0.27.0 Dec 23, 2024
0.26.1 Oct 29, 2024
0.26.0 Oct 26, 2024
0.25.1 Oct 25, 2024
0.25.0 Oct 24, 2024
0.24.3 Oct 24, 2024
0.24.2 Oct 23, 2024
0.24.1 Oct 22, 2024
0.24.0 Oct 20, 2024
0.23.0 Oct 12, 2024
0.22.3 Oct 05, 2024
0.22.2 Oct 04, 2024
0.22.1 Oct 03, 2024
0.22.0 Oct 03, 2024
0.21.0 Sep 30, 2024
0.20.0 Sep 18, 2024
0.19.1 Sep 15, 2024
0.19.0 Sep 14, 2024

Wheel compatibility matrix

Platform CPython >=3.10 (abi3) CPython (additional flags: t) 3.14 CPython (additional flags: t) 3.15 PyPy 3.11 (pp73) PyPy 3.11 (pp80)
macosx_10_12_universal2
macosx_10_12_x86_64
macosx_11_0_arm64
manylinux2014_i686
manylinux2014_x86_64
manylinux_2_17_i686
manylinux_2_17_x86_64
manylinux_2_28_aarch64
musllinux_1_2_aarch64
musllinux_1_2_x86_64
win32
win_amd64
win_arm64

Files in release

jsonschema_rs-0.58.1-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (10.5MiB)
jsonschema_rs-0.58.1-cp310-abi3-macosx_10_12_x86_64.whl (5.5MiB)
jsonschema_rs-0.58.1-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl (5.4MiB)
jsonschema_rs-0.58.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.6MiB)
jsonschema_rs-0.58.1-cp310-abi3-manylinux_2_28_aarch64.whl (5.2MiB)
jsonschema_rs-0.58.1-cp310-abi3-musllinux_1_2_aarch64.whl (5.4MiB)
jsonschema_rs-0.58.1-cp310-abi3-musllinux_1_2_x86_64.whl (5.9MiB)
jsonschema_rs-0.58.1-cp310-abi3-win32.whl (4.9MiB)
jsonschema_rs-0.58.1-cp310-abi3-win_amd64.whl (5.6MiB)
jsonschema_rs-0.58.1-cp310-abi3-win_arm64.whl (5.3MiB)
jsonschema_rs-0.58.1-cp314-cp314t-macosx_10_12_x86_64.whl (5.6MiB)
jsonschema_rs-0.58.1-cp314-cp314t-macosx_11_0_arm64.whl (5.1MiB)
jsonschema_rs-0.58.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.7MiB)
jsonschema_rs-0.58.1-cp314-cp314t-manylinux_2_28_aarch64.whl (5.2MiB)
jsonschema_rs-0.58.1-cp314-cp314t-musllinux_1_2_aarch64.whl (5.4MiB)
jsonschema_rs-0.58.1-cp314-cp314t-musllinux_1_2_x86_64.whl (5.9MiB)
jsonschema_rs-0.58.1-cp314-cp314t-win_amd64.whl (5.7MiB)
jsonschema_rs-0.58.1-cp314-cp314t-win_arm64.whl (5.4MiB)
jsonschema_rs-0.58.1-cp315-cp315t-macosx_10_12_x86_64.whl (5.6MiB)
jsonschema_rs-0.58.1-cp315-cp315t-macosx_11_0_arm64.whl (5.1MiB)
jsonschema_rs-0.58.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.7MiB)
jsonschema_rs-0.58.1-cp315-cp315t-manylinux_2_28_aarch64.whl (5.2MiB)
jsonschema_rs-0.58.1-cp315-cp315t-musllinux_1_2_aarch64.whl (5.4MiB)
jsonschema_rs-0.58.1-cp315-cp315t-musllinux_1_2_x86_64.whl (5.9MiB)
jsonschema_rs-0.58.1-cp315-cp315t-win_amd64.whl (5.7MiB)
jsonschema_rs-0.58.1-cp315-cp315t-win_arm64.whl (5.4MiB)
jsonschema_rs-0.58.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.7MiB)
jsonschema_rs-0.58.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl (5.2MiB)
jsonschema_rs-0.58.1-pp311-pypy311_pp80-macosx_10_12_x86_64.whl (5.5MiB)
jsonschema_rs-0.58.1-pp311-pypy311_pp80-win_amd64.whl (5.7MiB)
jsonschema_rs-0.58.1.tar.gz (2.7MiB)
Extras:
Dependencies: