50 个版本 (23 个重大更新)

0.24.0 2024年6月22日
0.22.0 2024年6月15日
0.19.0 2024年3月2日
0.16.3 2023年7月30日
0.6.2 2022年7月31日

#79 in 编码

Download history • Rust 包仓库 3239/week @ 2024-05-01 • Rust 包仓库 3700/week @ 2024-05-08 • Rust 包仓库 3916/week @ 2024-05-15 • Rust 包仓库 3118/week @ 2024-05-22 • Rust 包仓库 4246/week @ 2024-05-29 • Rust 包仓库 4758/week @ 2024-06-05 • Rust 包仓库 4303/week @ 2024-06-12 • Rust 包仓库 4756/week @ 2024-06-19 • Rust 包仓库 5553/week @ 2024-06-26 • Rust 包仓库 4299/week @ 2024-07-03 • Rust 包仓库 5058/week @ 2024-07-10 • Rust 包仓库 4481/week @ 2024-07-17 • Rust 包仓库 6674/week @ 2024-07-24 • Rust 包仓库 7947/week @ 2024-07-31 • Rust 包仓库 8350/week @ 2024-08-07 • Rust 包仓库 6835/week @ 2024-08-14 • Rust 包仓库

每月下载 30,825
17crate中使用 (直接使用11个)

MIT 许可协议

220KB
4.5K SLoC

Serde Valid

Latest Version crate docs GitHub license

这是一个基于 JSON Schema 的,使用 serde 的验证工具。

用法

您派生 Validate 特性,并编写验证。

use serde_valid::Validate;

#[derive(Validate)]
struct Data {
    #[validate(minimum = 0)]
    #[validate(maximum = 10)]
    val: i32,
}

#[derive(Validate)]
enum DataEnum {
    Named {
        #[validate]
        a: Data,
    },
}

let s = DataEnum::Named {
    a: Data { val: 5 },
};

assert!(s.validate().is_ok());

特性标志

  • toml - 提供以 toml 格式的序列化和反序列化。
  • yaml - 提供以 yaml 格式的序列化和反序列化。
  • i128 - 支持 i128/u128 类型(默认)。
  • fluent - 使用 fluent 提供本地化。

验证

Serde Valid 支持基于 JSON Schema 的标准验证。

类型 Serde Valid(验证派生) Serde Valid(验证特性) JSON Schema
字符串 #[验证(最大长度= 5)] ValidateMaxLength maxLength
字符串 #[验证(最小长度= 5)] ValidateMinLength minLength
字符串 #[验证(模式= r"^\d{5}$")] ValidatePattern 模式
数字 #[验证(最大值= 5)] ValidateMaximum 最大值
数字 #[验证(最小值= 5)] ValidateMinimum 最小值
数字 #[验证(最大值(不包括)= 5)] ValidateExclusiveMaximum exclusiveMaximum
数字 #[验证(最小值(不包括)= 5)] ValidateExclusiveMinimum exclusiveMinimum
数字 #[验证(倍数= 5)] ValidateMultipleOf multipleOf
对象 #[验证(最大属性数= 5)] ValidateMaxProperties maxProperties
对象 #[验证(最小属性数= 5)] ValidateMinProperties minProperties
数组 #[验证(最大项数= 5)] ValidateMaxItems maxItems
数组 #[验证(最小项数= 5)] ValidateMinItems minItems
数组 #[验证(唯一项)] ValidateUniqueItems uniqueItems
泛型 #[验证(枚举= [5, 10, 15])] ValidateEnumerate enum

此外,[serde_valid::utils][module@crate::utils] 提供了 JSON Schema 规范中未描述的验证类型。

类型 Serde Valid(验证派生) Serde Valid(验证函数)
持续时间 #[验证(自定义= 持续时间最大值(SECOND))] 持续时间最大值
持续时间 #[验证(自定义= 持续时间最小值(ZERO))] 持续时间最小值
持续时间 #[验证(自定义= 持续时间最大值(不包括)(SECOND))] 持续时间最大值(不包括)
持续时间 #[验证(自定义= 持续时间最小值(不包括)(ZERO))] 持续时间最小值(不包括)

完整构造函数(反序列化)

Serde Valid 支持使用 serde_valid::json::FromJsonValue 特性完全构造方法。

use serde::Deserialize;
use serde_valid::Validate;
use serde_valid::json::{json, FromJsonValue};

#[derive(Debug, Deserialize, Validate)]
struct Data {
    #[validate(maximum = 100)]
    val: i32,
}

// Deserialization and Validation!! 🚀
let err = Data::from_json_value(json!({ "val": 123 })).unwrap_err();

assert_eq!(
    err.to_string(),
    json!({
        "errors": [],
        "properties": {
            "val": {
                "errors": ["The number must be `<= 100`."]
            }
        }
    })
    .to_string()
);

您可以通过仅使用 serde_valid 进行反序列化来强制进行验证,并从项目的 Cargo.toml 中删除 serde_json

序列化

对于序列化,提供了 serde_valid::json::ToJsonString 特性。

use serde::Serialize;
use serde_valid::Validate;
use serde_valid::json::{json, ToJsonString};

#[derive(Debug, Serialize, Validate)]
struct Data {
    #[validate(maximum = 100)]
    val: i32,
}

assert_eq!(
    Data{ val: 12i32 }.to_json_string().unwrap(),
    json!({ "val": 12i32 }).to_json_string().unwrap()
);

自定义消息

对于用户自定义消息,Serde Valid 提供了 message_fnmessage

use serde_json::json;
use serde_valid::Validate;

#[inline]
fn min_error_message(_params: &serde_valid::MinItemsError) -> String {
    "this is custom message_fn.".to_string()
}

#[derive(Validate)]
struct Data {
    #[validate(min_items = 4, message_fn = min_error_message)]
    #[validate(max_items = 2, message = "this is custom message.")]
    val: Vec<i32>,
}

let s = Data { val: vec![1, 2, 3] };

assert_eq!(
    s.validate().unwrap_err().to_string(),
    json!({
        "errors": [],
        "properties": {
            "val": {
                "errors": [
                    "this is custom message_fn.",
                    "this is custom message."
                ]
            }
        }
    })
    .to_string()
);

流畅本地化

需要 fluent 功能。

您还可以通过使用 fluent 功能来使用 fluent 本地化。

允许以下属性

  • #[验证(..., fluent("message-id",key1=value1, ...))]
  • #[验证(...,message_l10n= fluent("message-id",key1=value1, ...))]
use unic_langid::LanguageIdentifier;
use serde_json::json;
use serde_valid::{fluent::Localize, Validate};


#[derive(Validate)]
struct Data (
    #[validate(min_length = 3, fluent("name-min-length", min_length = 3))]
    String,
);

assert_eq!(
    Data("田中".to_string()).validate()
        .unwrap_err()
        .localize(&get_bundle("name-min-length = 名前の長さは { $min_length } 文字以上でないといけません。"))
        .to_string(),
    json!({
        "errors": ["名前の長さは \u{2068}3\u{2069} 文字以上でないといけません。"]
    })
    .to_string()
);

自定义验证

单错误验证

您可以使用 #[validate(custom = ...)] 使用您自定义的验证。

use serde_valid::Validate;

fn user_validation(_val: &i32) -> Result<(), serde_valid::validation::Error> {
    Ok(())
}

#[derive(Validate)]
struct Data {
    #[validate(custom = user_validation)]
    val: i32,
}

let s = Data { val: 1 };

assert!(s.validate().is_ok());

您也可以使用闭包。

use serde_valid::Validate;

fn user_validation(_val: &i32, param1: bool) -> Result<(), serde_valid::validation::Error> {
    Ok(())
}

#[derive(Validate)]
struct Data {
    #[validate(custom = |v| user_validation(v, true))]
    val: i32,
}

let s = Data { val: 1 };

assert!(s.validate().is_ok());

自定义验证适用于处理在 JSON Schema 中未定义的便利验证。serde_valid::utils::* 为特定类型提供了便利函数。

use serde_json::json;
use serde_valid::Validate;
use serde_valid::utils::{duration_maximum, duration_minimum};


#[derive(Validate)]
struct Data {
    #[validate(custom = duration_maximum(std::time::Duration::from_micros(5)))]
    #[validate(custom = duration_minimum(std::time::Duration::from_micros(0)))]
    val1: std::time::Duration,
}

let s = Data {
    val1: std::time::Duration::from_micros(1),
};

assert!(s.validate().is_ok());

多错误验证

如果您想在自定义验证方法中使用多个错误,可以使用与单错误相同的 #[validate(custom = ...)]

use serde_valid::Validate;

// 🚀 Just change the return type from `Result<(), Error>` to `Result<(), Vec<Error>>` !!
fn user_validation(_val: &i32) -> Result<(), Vec<serde_valid::validation::Error>> {
    Ok(())
}

#[derive(Validate)]
struct Data {
    #[validate(custom = user_validation)]
    val: i32,
}

let s = Data { val: 1 };

assert!(s.validate().is_ok());

多字段验证

现在,您可以使用 #[validate(custom = ...)] 进行多字段验证。

use serde_json::json;
use serde_valid::Validate;

fn sample_validation(val1: i32, val2: &str) -> Result<(), serde_valid::validation::Error> {
    Ok(())
}

#[derive(Validate)]
#[validate(custom = |s| sample_validation(s.val1, &s.val2))]
struct Data {
    val1: i32,
    val2: String,
}

let s = Data {
    val1: 1,
    val2: "val2".to_owned(),
};

assert!(s.validate().is_ok());

验证特质

通过实现验证特质,您的原始类型可以使用 Serde Valid 验证。

use serde_valid::Validate;

struct MyType(String);

impl serde_valid::ValidateMaxLength for MyType {
    fn validate_max_length(&self, max_length: usize) -> Result<(), serde_valid::MaxLengthError> {
        self.0.validate_max_length(max_length)
    }
}

#[derive(Validate)]
struct Data {
    #[validate(max_length = 5)]
    val: MyType,
}

let s = Data {
    val: MyType(String::from("😍👺🙋🏽👨‍🎤👨‍👩‍👧‍👦")),
};

assert!(s.validate().is_ok());

验证错误格式

命名结构体

字段错误输出到 properties

use serde_json::json;
use serde_valid::Validate;

#[derive(Validate)]
struct Data {
    #[validate(maximum = 4)]
    val: u32,
}

let s = Data { val: 5 };

assert_eq!(
    s.validate().unwrap_err().to_string(),
    json!({
        "errors": [],
        "properties": {
            "val": {
                "errors": ["The number must be `<= 4`."]
            }
        }
    })
    .to_string()
);

未命名结构体

字段错误输出到 items。对于 items 的键保证是正数字符串。

use serde_json::json;
use serde_valid::Validate;

#[derive(Validate)]
struct Data (
    #[validate(maximum = 4)] u32,
    #[validate(maximum = 3)] u32,
);

let s = Data ( 5, 4 );

assert_eq!(
    s.validate().unwrap_err().to_string(),
    json!({
        "errors": [],
        "items": {
            "0": {
                "errors": ["The number must be `<= 4`."]
            },
            "1": {
                "errors": ["The number must be `<= 3`."]
            }
        }
    })
    .to_string()
);

新类型

字段错误输出到 errors

use serde_json::json;
use serde_valid::Validate;

#[derive(Validate)]
struct Data (
    #[validate(maximum = 4)] u32
);

let s = Data (5);

assert_eq!(
    s.validate().unwrap_err().to_string(),
    json!({
        "errors": ["The number must be `<= 4`."]
    })
    .to_string()
);

命名枚举

变体错误输出到 properties

use serde_json::json;
use serde_valid::Validate;

#[derive(Validate)]
enum Data {
    Named {
        #[validate(maximum = 5)]
        a: i32,
        #[validate(maximum = 5)]
        b: i32,
    },
}

let s = Data::Named { a: 6, b: 6 };

assert_eq!(
    s.validate().unwrap_err().to_string(),
    json!({
        "errors": [],
        "properties": {
            "a": {
                "errors": ["The number must be `<= 5`."]
            },
            "b": {
                "errors": ["The number must be `<= 5`."]
            }
        }
    })
    .to_string()
);

未命名枚举

变体错误输出到 items。对于 items 的键保证是正数字符串。

use serde_json::json;
use serde_valid::Validate;

#[derive(Validate)]
enum Data {
    Unnamed (
        #[validate(maximum = 5)] i32,
        #[validate(maximum = 5)] i32,
    ),
}

let s = Data::Unnamed ( 6, 6 );

assert_eq!(
    s.validate().unwrap_err().to_string(),
    json!({
        "errors": [],
        "items": {
            "0": {
                "errors": ["The number must be `<= 5`."]
            },
            "1": {
                "errors": ["The number must be `<= 5`."]
            }
        }
    })
    .to_string()
);

新类型枚举

变体错误输出到 errors

use serde_json::json;
use serde_valid::Validate;

#[derive(Validate)]
enum Data {
    NewType (
        #[validate(maximum = 5)] i32,
    ),
}

let s = Data::NewType ( 6 );

assert_eq!(
    s.validate().unwrap_err().to_string(),
    json!({
        "errors": ["The number must be `<= 5`."]
    })
    .to_string()
);

依赖

~5–7.5MB
~132K SLoC