35 个不稳定版本

0.18.0 2024年5月7日
0.17.1 2023年7月5日
0.17.0 2023年3月16日
0.16.1 2022年10月20日
0.2.0 2020年3月30日

#9 in Web 编程

Download history 120012/week @ 2024-05-03 135862/week @ 2024-05-10 132481/week @ 2024-05-17 145225/week @ 2024-05-24 192213/week @ 2024-05-31 226994/week @ 2024-06-07 191026/week @ 2024-06-14 148817/week @ 2024-06-21 132200/week @ 2024-06-28 205474/week @ 2024-07-05 184813/week @ 2024-07-12 144976/week @ 2024-07-19 153696/week @ 2024-07-26 142635/week @ 2024-08-02 259145/week @ 2024-08-09 187756/week @ 2024-08-16

774,091 每月下载量
146 个 crate (78 直接) 中使用

MIT 许可证

575KB
14K SLoC

jsonschema

ci codecov Crates.io docs.rs gitter

一个 JSON 模式验证器的实现。它将模式编译成验证树,以尽可能快地进行验证。

支持的草案

  • 草案 7(除可选的 idn-hostname.json 测试用例外)
  • 草案 6
  • 草案 4(除可选的 bignum.json 测试用例外)

部分支持草案(一些关键字尚未实现)

  • 草案 2019-09(需要启用 draft201909 功能)
  • 草案 2020-12(需要启用 draft202012 功能)
# Cargo.toml
jsonschema = "0.18"

要验证某些模式并获取验证错误(如果有)

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

每个错误都有一个 instance_path 属性,它指示验证实例中错误部分的路径。它可以通过 .to_string() 或通过 Vec<String> 转换为 JSON 指针。

如果您只需要知道文档是否有效(这更快)

use jsonschema::is_valid;
use serde_json::json;

fn main() {
    let schema = json!({"maxLength": 5});
    let instance = json!("foo");
    assert!(is_valid(&schema, &instance));
}

或使用编译后的模式(推荐)

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 支持 Draft 2019-09 的 basicflag 输出样式,因此您可以使用 serde 序列化验证结果

use jsonschema::{Output, BasicOutput, JSONSchema};
use serde_json::json;

fn main() {
    let schema_json = json!({
        "title": "string value",
        "type": "string"
    });
    let instance = json!("some string");
    let schema = JSONSchema::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, 
        json!({
            "valid": true,
            "annotations": [
                {
                    "keywordLocation": "",
                    "instanceLocation": "",
                    "annotations": {
                        "title": "string value"
                    }
                }
            ]
        })
    );
}

自定义关键字

jsonschema 允许您通过定义自定义关键字来实现自定义验证逻辑。要使用您自己的关键字,您需要实现 Keyword trait 并通过 with_keyword 方法将其添加到 JSONSchema 实例中

use jsonschema::{
    paths::{JSONPointer, JsonPointerNode},
    ErrorIterator, JSONSchema, Keyword, ValidationError,
};
use serde_json::{json, Map, Value};
use std::iter::once;

struct MyCustomValidator;

impl Keyword for MyCustomValidator {
    fn validate<'instance>(
        &self,
        instance: &'instance Value,
        instance_path: &JsonPointerNode,
    ) -> ErrorIterator<'instance> {
        // ... validate instance ...
        if !instance.is_object() {
            let error = ValidationError::custom(
                JSONPointer::default(),
                instance_path.into(),
                instance,
                "Boom!",
            );
            Box::new(once(error))
        } else {
            Box::new(None.into_iter())
        }
    }
    fn is_valid(&self, instance: &Value) -> bool {
        // ... determine if instance is valid ...
        true
    }
}

// You can create a factory function, or use a closure to create new validator instances.
fn custom_validator_factory<'a>(
    // Parent object where your keyword is defined
    parent: &'a Map<String, Value>,
    // Your keyword value
    value: &'a Value,
    // JSON Pointer to your keyword within the schema
    path: JSONPointer,
) -> Result<Box<dyn Keyword>, ValidationError<'a>> {
    // You may return validation error if the keyword is misused for some reason
    Ok(Box::new(MyCustomValidator))
}

fn main() {
    let schema = json!({"my-type": "my-schema"});
    let instance = json!({"a": "b"});
    let compiled = JSONSchema::options()
        // Register your keyword via a factory function
        .with_keyword("my-type", custom_validator_factory)
        // Or use a closure
        .with_keyword("my-type-with-closure", |_, _, _| Ok(Box::new(MyCustomValidator)))
        .compile(&schema)
        .expect("A valid schema");
    assert!(compiled.is_valid(instance));
}

引用解析和 TLS

默认情况下,jsonschema 通过 reqwest 解析 HTTP 引用,但不支持 TLS。如果您想解析 HTTPS,您需要在 reqwest 中启用 TLS 支持

reqwest = { version = "*", features = [ "rustls-tls" ] }

否则,您可能会遇到如下的验证错误:无效的 URL方案不是 http

状态

此库功能齐全,可供使用,但其 API 仍在向 1.0 API 发展。

绑定

  • Python - 请参阅 ./bindings/python 目录
  • Ruby - 由 @driv3r 编写的 crate
  • NodeJS - 由 @ahungrynoob 编写的 package

运行测试

jsonschema/ 中的测试依赖于 JSON Schema 测试套件。在调用 cargo test 之前,请下载套件

$ git submodule init
$ git submodule update

以下命令将套件克隆到 jsonschema/tests/suite/

现在,进入 jsonschema 目录并运行 cargo test

$ cd jsonschema
$ cargo test

性能

与其他用 Rust 编写的 JSON Schema 验证器进行了比较 - jsonschema_valid==0.5.2valico==4.0.0

测试机器 i8700K (12 核心处理器),32GB RAM。

输入值和模式

案例 模式大小 实例大小
OpenAPI 18 KB 4.5 MB
Swagger 25 KB 3.0 MB
加拿大 4.8 KB 2.1 MB
CITM 目录 2.3 KB 501 KB
Fast(有效) 595 B 55 B
Fast(无效) 595 B 60 B

以下是每个竞争者进行验证的平均时间。比率是使用其 validate 方法针对编译的 JSONSchema 提供的。 is_valid 方法更快,但只返回布尔值

案例 jsonschema_valid valico jsonschema(验证) jsonschema(is_valid)
OpenAPI - (1) - (1) 3.500 毫秒 3.147 毫秒(x0.89
Swagger - (2) 180.65 毫秒(x32.12 5.623 毫秒 3.634 毫秒(x0.64
加拿大 40.363 毫秒(x33.13 427.40 毫秒(x350.90 1.218 毫秒 1.217 毫秒(x0.99
CITM 目录 5.357 毫秒(x2.51 39.215 毫秒(x18.44 2.126 毫秒 569.23 微秒(x0.26
Fast(有效) 2.27 微秒(x4.87 6.55 微秒(x14.05 465.89 纳秒 113.94 纳秒(x0.24
Fast(无效) 412.21 纳秒(x0.46 6.69 微秒(x7.61 878.23 纳秒 4.21 纳秒(x0.004

备注

  1. jsonschema_validvalico 无法处理与正则表达式 ^\\/ 匹配的有效路径实例。

  2. jsonschema_valid 无法解析本地引用(例如 #/definitions/definitions)。

您可以在 benches/jsonschema.rs 中找到基准代码,Rust 版本是 1.78

支持

如果您想讨论有关此库的任何内容,请加入我们的 gitter

依赖关系

~9–21MB
~330K SLoC