23个版本 (破坏性)
0.18.1 | 2024年4月11日 |
---|---|
0.17.0 | 2024年3月4日 |
0.16.1 | 2023年6月15日 |
0.16.0 | 2022年7月25日 |
0.1.0 | 2016年12月28日 |
#17 in Rust模式
774,957 每月下载量
用于 332 个crate (220 直接)
74KB
1.5K SLoC
validator
Macros 1.1自定义特性,用于简化结构验证,灵感来自 marshmallow 和 Django验证器。
最低支持版本为Rust 1.42。
安装
[dependencies]
validator = { version = "0.16", features = ["derive"] }
简短示例
use serde::Deserialize;
// A trait that the Validate derive will impl
use validator::{Validate, ValidationError};
#[derive(Debug, Validate, Deserialize)]
struct SignupData {
#[validate(email)]
mail: String,
#[validate(url)]
site: String,
#[validate(length(min = 1), custom(function = "validate_unique_username"))]
#[serde(rename = "firstName")]
first_name: String,
#[validate(range(min = 18, max = 20))]
age: u32,
#[validate(range(exclusive_min = 0.0, max = 100.0))]
height: f32,
}
fn validate_unique_username(username: &str) -> Result<(), ValidationError> {
if username == "xXxShad0wxXx" {
// the value of the username will automatically be added later
return Err(ValidationError::new("terrible_username"));
}
Ok(())
}
match signup_data.validate() {
Ok(_) => (),
Err(e) => return e;
};
对一个 Option<_>
字段的验证将在选项为 Some
时对包含的类型执行。 validate()
方法返回一个 Result<(), ValidationErrors>
。如果结果无效,则 ValidationErrors
实例包括一个错误映射,键是结构的字段名。错误可以用三种方式表示,如 ValidationErrorsKind
枚举中所述
#[derive(Debug, Serialize, Clone, PartialEq)]
#[serde(untagged)]
pub enum ValidationErrorsKind {
Struct(Box<ValidationErrors>),
List(BTreeMap<usize, Box<ValidationErrors>>),
Field(Vec<ValidationError>),
}
在上面的简单示例中,任何错误都将是 Field(Vec<ValidationError>)
类型,其中单个 ValidationError
具有以下结构
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ValidationError {
pub code: Cow<'static, str>,
pub message: Option<Cow<'static, str>>,
pub params: HashMap<Cow<'static, str>, Value>,
}
字段的值将自动添加到具有 value
键的参数中。
请注意,validator
与 serde 一起工作:在示例中,我们可以看到 first_name
字段已从/to firstName
重命名。该字段的任何错误都将位于哈希表的 firstName
键中,而不是 first_name
。
其他两个 ValidationErrorsKind
类型表示在嵌套(结构体的向量)中发现的错误,如下例所述。
use serde::Deserialize;
// A trait that the Validate derive will impl
use validator::Validate;
#[derive(Debug, Validate, Deserialize)]
struct SignupData {
#[validate]
contact_details: ContactDetails,
#[validate]
preferences: Vec<Preference>,
#[validate(required)]
allow_cookies: Option<bool>,
}
#[derive(Debug, Validate, Deserialize)]
struct ContactDetails {
#[validate(email)]
mail: String,
}
#[derive(Debug, Validate, Deserialize)]
struct Preference {
#[validate(length(min = 4))]
name: String,
value: bool,
}
match signup_data.validate() {
Ok(_) => (),
Err(e) => return e;
};
在这里,ContactDetails
和 Preference
结构体嵌套在父 SignupData
结构体中。因为这些子类型也派生了 Validate
,所以它们出现的字段可以被标记为包含在父结构体的验证方法中。
在单个嵌套结构体(本例中的 contact_details
字段)中发现的任何错误都会以父结构体的 ValidationErrors
结果中的 Struct(Box<ValidationErrors>)
类型返回。
在嵌套结构体的向量(本例中的 preferences
字段)中发现的任何错误都会以父结构体的 ValidationErrors
结果中的 List(BTreeMap<usize, Box<ValidationErrors>>)
类型返回,其中映射是以无效向量条目索引为键。
用法
您需要导入 Validate
特性。
validator
库也可以在不使用自定义 derive 的情况下使用,因为它公开了所有验证函数和类型。
验证器
库附带一些内置验证器,并且可以为给定的字段设置多个验证器。
检查 String 是否是有效的电子邮件地址,根据 HTML5 正则表达式,这意味着它将标记一些古怪的电子邮件地址为无效,这些地址在 email
输入中也不会有效。此验证器不接受任何参数:#[validate(email)]
。
url
检查 String 是否是有效的 URL。此验证器不接受任何参数:#[validate(url)]
;
length
检查 String 或 Vec 是否满足给定的长度要求。 length
有 3 个整数参数
- min
- max
- equal
使用 equal
排除了 min
或 max
,如果找到它们将导致编译错误。
至少需要一个参数,最多两个(同时拥有 min
和 max
)。
示例
const MIN_CONST: u64 = 1;
const MAX_CONST: u64 = 10;
#[validate(length(min = 1, max = 10))]
#[validate(length(min = 1))]
#[validate(length(max = 10))]
#[validate(length(equal = 10))]
#[validate(length(min = "MIN_CONST", max = "MAX_CONST"))]
range
检查数字是否在给定的范围内。 range
有 1 或 2 个参数,它们可以是普通(min
和 max
)或排他性(exclusive_min
、exclusive_max
、无法达到的极限)。这些可以是数字或值路径。
示例
const MAX_CONSTANT: i32 = 10;
const MIN_CONSTANT: i32 = 0;
#[validate(range(min = 1))]
#[validate(range(min = "MIN_CONSTANT"))]
#[validate(range(min = 1, max = 10))]
#[validate(range(min = 1.1, max = 10.8))]
#[validate(range(max = 10.8))]
#[validate(range(min = "MAX_CONSTANT"))]
#[validate(range(min = "crate::MAX_CONSTANT"))]
#[validate(range(exclusive_min = 0.0, max = 100.0))]
#[validate(range(exclusive_max = 10))]
must_match
检查两个字段是否相等。 must_match
有一个字符串参数。如果提及的字段缺失或类型与属性所在字段不同,它将引发错误。
示例
#[validate(must_match = "password2")]
#[validate(must_match(other = "password2"))]
包含
判断字符串是否包含指定的子串或哈希表中的键是否存在。contains
接受1个字符串参数。
示例
#[validate(contains = "gmail")]
#[validate(contains(pattern = "gmail"))]
not_contain
基本上是包含的反义词,只是为了方便使用。判断容器是否不包含指定的子串(如果是字符串)或哈希表中的键不存在。does_not_contain
接受1个字符串参数。
示例
#[validate(does_not_contain = "gmail")]
#[validate(does_not_contain(pattern = "gmail"))]
regex
判断字符串是否与给定的正则表达式匹配。regex
接受1个字符串参数:静态 Regex 实例的路径。
示例
use once_cell::sync::Lazy;
static RE_TWO_CHARS: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"[a-z]{2}$").unwrap()
});
#[validate(regex = "RE_TWO_CHARS")]
#[validate(regex(path = "RE_TWO_CHARS"))]
credit_card
测试字符串是否是有效的信用卡号。
示例
#[validate(credit_card)]
custom
调用你的一个函数来执行自定义验证。字段引用将作为参数传递给函数,函数应返回一个 Result<(), ValidationError>
。
示例
#[validate(custom(function = "validate_something"))]
#[validate(custom(function = "::utils::validate_something"))]
您还可以通过设置 arg
参数从验证函数解析参数到您的自定义验证。 arg
只能设置为一个类型,但您可以将其设置为元组以一次性传递多个类型。定义 arg
参数将实现 ValidateArgs
trait,如下所示
use validator::{Validate, ValidateArgs, ValidationError};
fn validate(value: &str, arg: (i64, i64)) -> Result<(), ValidationError> {
[...]
}
#[derive(Debug, Validate)]
struct TestStruct {
#[validate(custom(function = "validate", arg = "(i64, i64)"))]
value: String,
}
let test_struct: TestStruct = [...]
test_struct.validate_args((77, 555)).is_ok();
您还可以使用生命周期 'v_a
通过使用来传递引用,请注意,这个生命周期应该只用于像这样的函数参数
fn validate_value(_: &str, arg: &mut Database) -> Result<(), ValidationError> {
[...]
}
#[derive(Debug, Validate)]
struct TestStruct {
// vvvv This is the lifetime for references
#[validate(custom(function = "validate_value", arg = "&'v_a mut Database"))]
value: String,
}
let mut database: Database = [...]
let test_struct: TestStruct = [...]
test_struct.validate_args(&mut database).is_ok();
带参数的自定义验证不适用于嵌套验证。有关更多示例,请参阅 validator_derive_tests/tests/custom.rs
和 validator_derive_tests/tests/custom_args.rs
。
nested
对具有实现 Validate trait 的类型(或此类类型的向量)的字段执行验证。
示例
#[validate]
non_control_character
测试字符串是否包含任何 utf-8 控制字符,如果包含则验证失败。要使用此验证器,您必须为 validator
crate 启用 unic
功能。此验证器不接受任何参数: #[validate(non_control_character)]
;
required
测试 Option<T>
字段是否为 Some
;
结构级验证
通常,某些错误验证只能在查看整个结构时应用,这里是如何工作的
#[derive(Debug, Validate, Deserialize)]
#[validate(schema(function = "validate_category", skip_on_field_errors = false))]
struct CategoryData {
category: String,
name: String,
}
提到的函数应返回一个 Result<(), ValidationError>
,并且将在所有字段验证完成后被调用。
如果未指定,则 skip_on_field_errors
默认为 true
,这将确保如果结构字段验证过程中发生错误,则不会调用该函数。
结构级验证中的任何错误都将出现在错误哈希表的键 __all__
中。
消息和代码
除了它们自己的参数外,每个验证器还可以接受2个可选参数
message
:一个与错误一起的消息,例如,如果您想进行 i18n代码
:每个验证器都有一个默认的错误代码(例如,正则表达式
验证器代码是正则表达式
),但在必要时可以重写,主要需要用于自定义
验证器
请注意,这些参数不能应用于带有#[validate]
的嵌套验证调用。
例如,以下属性都有效
// code attribute
#[validate(email(code = "code_str"))]
#[validate(credit_card(code = "code_str"))]
#[validate(length(min = 5, max = 10, code = "code_str"))]
#[validate(regex(path = "static_regex", code = "code_str"))]
#[validate(custom(function = "custom_fn", code = "code_str"))]
#[validate(contains(pattern = "pattern_str", code = "code_str"))]
#[validate(does_not_contain(pattern = "pattern_str", code = "code_str"))]
#[validate(must_match(other = "match_value", code = "code_str"))]
// message attribute
#[validate(url(message = "message_str"))]
#[validate(length(min = 5, max = 10, message = "message_str"))]
#[validate(regex(path = "static_regex", message = "message_str"))]
#[validate(custom(function = "custom_fn", message = "message_str"))]
#[validate(contains(pattern = "pattern_str", message = "message_str"))]
#[validate(does_not_contain(pattern = "pattern_str", message = "message_str"))]
#[validate(must_match(other = "match_value", message = "message_str"))]
// both attributes
#[validate(url(message = "message", code = "code_str"))]
#[validate(email(code = "code_str", message = "message"))]
#[validate(custom(function = "custom_fn", code = "code_str", message = "message_str"))]
依赖项
~4.5-7MB
~149K SLoC