Go to file
Dmitry Dygalo 4a07ba9a82
chore: Update to Rust 2021 edition in all crates
2022-04-10 23:31:34 +02:00
.github build: Set precise runner versions 2022-04-01 09:49:01 +02:00
bench_helpers chore: Update to Rust 2021 edition in all crates 2022-04-10 23:31:34 +02:00
bindings/python chore: Update to Rust 2021 edition in all crates 2022-04-10 23:31:34 +02:00
jsonschema chore: Update to Rust 2021 edition in all crates 2022-04-10 23:31:34 +02:00
jsonschema-test-suite chore: Update to Rust 2021 edition in all crates 2022-04-10 23:31:34 +02:00
perf-helpers chore: Update to Rust 2021 edition in all crates 2022-04-10 23:31:34 +02:00
.gitignore chore: Port `json-schema-test-suite` as a local dependency 2021-07-23 10:17:53 +02:00
.gitmodules Fetch git submodule with https instead of ssh 2021-02-15 10:07:35 +01:00
.pre-commit-config.yaml chore: Update pre-commit 2022-04-01 09:49:01 +02:00
.yamllint
CHANGELOG.md docs: Update changelog 2022-04-10 23:28:34 +02:00
CODE_OF_CONDUCT.md
LICENSE docs: Update LICENSE years 2021-12-25 00:17:27 +01:00
README.md fix: Enable `reqwest/native-tls` by default to avoid validation errors caused by `reqwest` missing a TLS backend 2022-04-02 17:50:14 +02:00
codecov.yaml

README.md

jsonschema

ci codecov Crates.io docs.rs gitter

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.15"

By default jsonschema resolves remote references via HTTP by using reqwest with native-tls. If you'd like to use rustls, you have to explicitly enable reqwest and rustls features and disable native-tls via default-features = false in your Cargo.toml file.

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));
}

Output styles

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"
                    }
                }
            ]
        })
    );
}

Status

This library is functional and ready for use, but its API is still evolving to the 1.0 API.

Bindings

  • Python - See the ./bindings/python directory
  • Ruby - a crate by @driv3r
  • NodeJS - a package by @ahungrynoob

Performance

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:

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:

  1. jsonschema_valid and valico do not handle valid path instances matching the ^\\/ regex.

  2. 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.

Support

If you have anything to discuss regarding this library, please, join our gitter!