A JSON Schema validator implementation. It compiles schema into a validation tree to have validation as fast as possible.
Supported drafts:
- Draft 7 (except optional
idn-hostname.json
test case) - Draft 6
- Draft 4 (except optional
bignum.json
test case)
Partially supported drafts (some keywords are not implemented):
- Draft 2019-09 (requires the
draft201909
feature enabled) - Draft 2020-12 (requires the
draft202012
feature enabled)
# Cargo.toml
jsonschema = "0.16"
To validate documents against some schema and get validation errors (if any):
use jsonschema::JSONSchema;
use serde_json::json;
fn main() {
let schema = json!({"maxLength": 5});
let instance = json!("foo");
let compiled = JSONSchema::compile(&schema)
.expect("A valid schema");
let result = compiled.validate(&instance);
if let Err(errors) = result {
for error in errors {
println!("Validation error: {}", error);
println!(
"Instance path: {}", error.instance_path
);
}
}
}
Each error has an instance_path
attribute that indicates the path to the erroneous part within the validated instance.
It could be transformed to JSON Pointer via .to_string()
or to Vec<String>
via .into_vec()
.
If you only need to know whether document is valid or not (which is faster):
use jsonschema::is_valid;
use serde_json::json;
fn main() {
let schema = json!({"maxLength": 5});
let instance = json!("foo");
assert!(is_valid(&schema, &instance));
}
Or use a compiled schema (preferred):
use jsonschema::JSONSchema;
use serde_json::json;
fn main() {
let schema = json!({"maxLength": 5});
let instance = json!("foo");
// Draft is detected automatically
// with fallback to Draft7
let compiled = JSONSchema::compile(&schema)
.expect("A valid schema");
assert!(compiled.is_valid(&instance));
}
jsonschema
supports basic
& flag
output styles from Draft 2019-09, so you can serialize the validation results with serde
:
use jsonschema::{Output, BasicOutput, JSONSchema};
fn main() {
let schema_json = serde_json::json!({
"title": "string value",
"type": "string"
});
let instance = serde_json::json!{"some string"};
let schema = JSONSchema::options()
.compile(&schema_json)
.expect("A valid schema");
let output: BasicOutput = schema.apply(&instance).basic();
let output_json = serde_json::to_value(output)
.expect("Failed to serialize output");
assert_eq!(
output_json,
serde_json::json!({
"valid": true,
"annotations": [
{
"keywordLocation": "",
"instanceLocation": "",
"annotations": {
"title": "string value"
}
}
]
})
);
}
By default, jsonschema
resolves HTTP references via reqwest
without TLS support.
If you'd like to resolve HTTPS, you need to enable TLS support in reqwest
:
reqwest = { version = "*", features = [ "rustls-tls" ] }
Otherwise, you might get validation errors like invalid URL, scheme is not http
.
This library is functional and ready for use, but its API is still evolving to the 1.0 API.
- Python - See the
./bindings/python
directory - Ruby - a crate by @driv3r
- NodeJS - a package by @ahungrynoob
There is a comparison with other JSON Schema validators written in Rust - jsonschema_valid==0.4.0
and valico==3.6.0
.
Test machine i8700K (12 cores), 32GB RAM.
Input values and schemas:
- Zuora OpenAPI schema (
zuora.json
). Validated against OpenAPI 3.0 JSON Schema (openapi.json
). - Kubernetes Swagger schema (
kubernetes.json
). Validated against Swagger JSON Schema (swagger.json
). - Canadian border in GeoJSON format (
canada.json
). Schema is taken from the GeoJSON website (geojson.json
). - Concert data catalog (
citm_catalog.json
). Schema is inferred via infers-jsonschema & manually adjusted (citm_catalog_schema.json
). Fast
is taken from fastjsonschema benchmarks (fast_schema.json
,fast_valid.json
andfast_invalid.json
).
Case | Schema size | Instance size |
---|---|---|
OpenAPI | 18 KB | 4.5 MB |
Swagger | 25 KB | 3.0 MB |
Canada | 4.8 KB | 2.1 MB |
CITM catalog | 2.3 KB | 501 KB |
Fast (valid) | 595 B | 55 B |
Fast (invalid) | 595 B | 60 B |
Here is the average time for each contender to validate. Ratios are given against compiled JSONSchema
using its validate
method. The is_valid
method is faster, but gives only a boolean return value:
Case | jsonschema_valid | valico | jsonschema (validate) | jsonschema (is_valid) |
---|---|---|---|---|
OpenAPI | - (1) | - (1) | 4.717 ms | 4.279 ms (x0.90) |
Swagger | - (2) | 83.357 ms (x12.47) | 6.681 ms | 4.533 ms (x0.67) |
Canada | 32.987 ms (x31.38) | 141.41 ms (x134.54) | 1.051 ms | 1.046 ms (x0.99) |
CITM catalog | 4.735 ms (x2.00) | 13.222 ms (x5.58) | 2.367 ms | 535.07 us (x0.22) |
Fast (valid) | 2.00 us (x3.85) | 3.18 us (x6.13) | 518.39 ns | 97.91 ns (x0.18) |
Fast (invalid) | 339.28 ns (x0.50) | 3.34 us (x5.00) | 667.55 ns | 5.41ns (x0.01) |
Notes:
-
jsonschema_valid
andvalico
do not handle valid path instances matching the^\\/
regex. -
jsonschema_valid
fails to resolve local references (e.g.#/definitions/definitions
).
You can find benchmark code in benches/jsonschema.rs
, Rust version is 1.57
.
If you have anything to discuss regarding this library, please, join our gitter!