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 3239/week @ 2024-05-01 3700/week @ 2024-05-08 3916/week @ 2024-05-15 3118/week @ 2024-05-22 4246/week @ 2024-05-29 4758/week @ 2024-06-05 4303/week @ 2024-06-12 4756/week @ 2024-06-19 5553/week @ 2024-06-26 4299/week @ 2024-07-03 5058/week @ 2024-07-10 4481/week @ 2024-07-17 6674/week @ 2024-07-24 7947/week @ 2024-07-31 8350/week @ 2024-08-07 6835/week @ 2024-08-14

每月下载 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