Skip to main content

rsonschema

Crates.io docs.rs PyPI CI License

A fast, simple, and user-friendly JSON Schema validator for Rust, with Python bindings.

Prologue

In the world of data validation, ensuring your data conforms to a specified structure is crucial.

At hiop, we sought a language-agnostic format to define how data should be structured, and JSON Schema stood out as the perfect solution.

This inspired the creation of rsonschema, a fast, simple, and user-friendly JSON Schema validator for Rust.

Why Rust?

Rust is celebrated for its performance and safety capabilities. These attributes make it an excellent choice for building a fast, user-friendly, secure, and efficient validator.

Alternatives

  • jsonschema: was previously our choice, offering robust validation but suffering from complex error handling. For example:

    1. jsonschema::error::ValidationError borrows the instance attribute, adding complexity.
    2. it lacks useful error messages for end users, especially when validating schemas with Schema Composition failures.
  • valico: like jsonschema, it has complex error handling. Moreover it is not actively maintained.

  • schemars: a de facto standard for schema generation with over 19 million downloads. However, it lacks validation APIs.

Usage

Rust

Add rsonschema to your Cargo.toml:

cargo add rsonschema

Here's how you can start using rsonschema in your Rust project:

let schema = serde_json::json!({
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "minLength": 3
});

let instance = serde_json::json!("foo");
let report = rsonschema::validate(
    &instance,
    schema.clone(),
);
assert!(report.is_valid());

let instance = serde_json::json!("a");
let report = rsonschema::validate(
    &instance,
    schema,
);
assert_eq!(
    report,
    rsonschema::ValidationReport {
        errors: Some(
            rsonschema::error::ValidationErrors::from([
                rsonschema::error::ValidationError {
                    instance: serde_json::json!("a"),
                    type_: rsonschema::error::type_::ValidationErrorType::MinLength {
                        limit: 3.into(),
                    },
                    ..Default::default()
                }
            ])
        ),
        ..Default::default()
    }
);

Python

Install from PyPI (requires Python >= 3.10):

pip install rsonschema
import rsonschema

schema = {"$schema": "https://json-schema.org/draft/2020-12/schema", "minLength": 3}

# validate(instance, schema, pointer=None, ref_resolver=None)
errors = rsonschema.validate("foo", schema, None, None)
assert errors == []

errors = rsonschema.validate("a", schema, None, None)
assert len(errors) == 1
assert str(errors[0])  # human-readable error description

Error Messages

One of rsonschema's key strengths is the quality of its human-readable error messages. Each error includes the failing value, the full path to it within the document, and a precise description — making them suitable to display directly to end users.

Simple constraint violation

let schema = serde_json::json!({
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "string",
    "minLength": 5
});

let report = rsonschema::validate(&serde_json::json!("hi"), schema);
let error = report.errors.unwrap().into_iter().min().unwrap();
println!("{error}");
// "hi": must be longer than `5` characters

Nested objects

The pointer tracks the full path from the document root to the failing value:

let schema = serde_json::json!({
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "properties": {
        "user": {
            "required": ["name", "email"]
        }
    }
});

let report = rsonschema::validate(
    &serde_json::json!({"user": {"name": "Alice"}}),
    schema,
);
let error = report.errors.unwrap().into_iter().min().unwrap();
println!("{error}");
// {"name":"Alice"} at `user`: missing required: `email`

Schema composition (anyOf, oneOf, allOf)

When validation fails on a composition keyword, rsonschema surfaces the most relevant inner error rather than a generic "did not match any schema" message. Relevance is determined by how closely the instance resembles each branch, using string similarity on values and property names.

let schema = serde_json::json!({
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "anyOf": [
        {"type": "string", "minLength": 5},
        {"type": "integer", "minimum": 10}
    ]
});

let report = rsonschema::validate(&serde_json::json!("hi"), schema);
let error = report.errors.unwrap().into_iter().min().unwrap();
println!("{error}");
// "hi": must be longer than `5` characters

"hi" is clearly closer to the string branch, so the minLength error from that branch is surfaced instead of a generic composition failure.

Python bindings

The same messages are available via the .message attribute on each error object:

import rsonschema

schema = {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "properties": {
        "user": {"required": ["name", "email"]}
    },
}
errors = rsonschema.validate({"user": {"name": "Alice"}}, schema, None, None)
print(str(errors[0]))
# {"name":"Alice"} at `user`: missing required: `email`

Performance

rsonschema is benchmarked against jsonschema across representative scenarios. Selected results on Apple M3 (lower is better):

Scenario rsonschema jsonschema (cold)
Simple string validation 738 ns 2.14 µs
Complex object (5 fields) 6.85 µs 8.95 µs
Array of 50 objects 54.0 µs 7.74 µs
anyOf composition 3.25 µs 4.91 µs

Cold means the competitor also compiles the schema on every call, matching rsonschema's usage model. See BENCHMARKS.md for the full methodology and results, including Python bindings.

Scope

rsonschema targets a specific, well-defined subset of JSON Schema:

  • Draft: only the latest (2020-12) specification is supported. Older drafts are not.
  • Validation only: the library validates instances against schemas and reports errors — it does not generate schemas or produce annotation output.
  • All standard keywords are implemented, including schema composition (allOf, anyOf, oneOf, not), conditionals (if/then/else), references ($ref, $anchor), unevaluated keywords (unevaluatedProperties, unevaluatedItems), and format assertions.
  • Intentionally unsupported: dynamic keywords $dynamicAnchor and $dynamicRef are excluded because they introduce significant complexity with limited practical benefit.

All official JSON Schema Test Suite tests, located in the tests folder, pass — except for the unsupported dynamic keywords above.

Community

Contribution

We firmly believe that collaboration is the key to innovation!

If you find a bug or have a feature request, please open an issue. If you want to go further and tackle it, open a pull request on our GitHub repository.

See CONTRIBUTING.md for development guidelines.

License

rsonschema is licensed under the Apache-2.0 License. See the LICENSE file for more details.

Release files for rsonschema 0.1.16

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for rsonschema 0.1.16
File
rsonschema-0.1.16-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
rsonschema-0.1.16-cp314-cp314-macosx_10_12_x86_64.whl CPython 3.14 CPython 3.14 macOS 10.12+ x86-64 Details
rsonschema-0.1.16-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
rsonschema-0.1.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.8 CPython 3.8 Linux glibc 2.17+ x86-64 Details

Total release size: 13.1 MB

Release files / rsonschema-0.1.16-cp314-cp314-macosx_11_0_arm64.whl

Download URL rsonschema-0.1.16-cp314-cp314-macosx_11_0_arm64.whl
Size 3.2 MB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
6fe5ae7647ebbd2ae6dcfae8364f1d07716753fc3cfbbbd52d753238b31fa883
BLAKE2b-256 checksum
How to use checksums
ddbf89253459ece3a5b701cb6b1143e6e0a85ef0d7386a0802c7049800bec08a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.

Transparency log

Release files / rsonschema-0.1.16-cp314-cp314-macosx_10_12_x86_64.whl

Download URL rsonschema-0.1.16-cp314-cp314-macosx_10_12_x86_64.whl
Size 3.3 MB
Tags CPython 3.14 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
90d55f704358c391d610ae3287b3077a5188086fb297f4373d4902b19a35b372
BLAKE2b-256 checksum
How to use checksums
26e0c0000426ca71f776b278db504ef974f8111f8a4af90aa9389dc3f6d88299
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.

Transparency log

Release files / rsonschema-0.1.16-cp312-cp312-win_amd64.whl

Download URL rsonschema-0.1.16-cp312-cp312-win_amd64.whl
Size 3.0 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
f569e9de6e5c109fd31085be937fdfcc5748c4c7459b09fe09c8154eace24b44
BLAKE2b-256 checksum
How to use checksums
80905a6ced5fde24c89695b8fde7c8403873c0804af8bef7bc811e7df49f4c9e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.

Transparency log

Release files / rsonschema-0.1.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL rsonschema-0.1.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.6 MB
Tags CPython 3.8 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
8b22af99790cfc39e6ec6f167fe7343408bede05c1a0f1496fe4ad9bd6697fc9
BLAKE2b-256 checksum
How to use checksums
f32d86abbb576ec656dfcc63ce3df8a0d0ddf92587dab8993a4314e14f4ad490
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.16 This release

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page