rsonschema
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:
jsonschema::error::ValidationErrorborrows theinstanceattribute, adding complexity.- 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
$dynamicAnchorand$dynamicRefare 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)
| File | Reset | |||
|---|---|---|---|---|
| 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 logRelease 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 logRelease 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 logRelease 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