Crate serde_valid
source ·Expand description
§Serde Valid
This is JSON Schema based validation tool using serde.
§Usage
You derive Validate
trait, and write validations.
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());
§Feature Flags
toml
- provide serialization/deserialization intoml
format.yaml
- provide serialization/deserialization inyaml
format.i128
- supporti128
/u128
type (default).fluent
- provide localization using fluent.
§Validations
Serde Valid support standard validation based JSON Schema.
Type | Serde Valid (validate derive) | Serde Valid (validate trait) | JSON Schema |
---|---|---|---|
String | #[validate(max_length = 5)] | ValidateMaxLength | maxLength |
String | #[validate(min_length = 5)] | ValidateMinLength | minLength |
String | #[validate(pattern = r"^\d{5}$")] | ValidatePattern | pattern |
Numeric | #[validate(maximum = 5)] | ValidateMaximum | maximum |
Numeric | #[validate(minimum = 5)] | ValidateMinimum | minimum |
Numeric | #[validate(exclusive_maximum = 5)] | ValidateExclusiveMaximum | exclusiveMaximum |
Numeric | #[validate(exclusive_minimum = 5)] | ValidateExclusiveMinimum | exclusiveMinimum |
Numeric | #[validate(multiple_of = 5)] | ValidateMultipleOf | multipleOf |
Object | #[validate(max_properties = 5)] | ValidateMaxProperties | maxProperties |
Object | #[validate(min_properties = 5)] | ValidateMinProperties | minProperties |
Array | #[validate(max_items = 5)] | ValidateMaxItems | maxItems |
Array | #[validate(min_items = 5)] | ValidateMinItems | minItems |
Array | #[validate(unique_items)] | ValidateUniqueItems | uniqueItems |
Generic | #[validate(enumerate = [5, 10, 15])] | ValidateEnumerate | enum |
In addition, serde_valid::utils provides a type of validation not described in the JSON schema specification.
Type | Serde Valid (validate derive) | Serde Valid (validation function) |
---|---|---|
Duration | #[validate(custom = duration_maximum(SECOND))] | duration_maximum |
Duration | #[validate(custom = duration_minimum(ZERO))] | duration_minimum |
Duration | #[validate(custom = duration_exclusive_maximum(SECOND))] | duration_exclusive_maximum |
Duration | #[validate(custom = duration_exclusive_minimum(ZERO))] | duration_exclusive_minimum |
§Complete Constructor (Deserialization)
Serde Valid support complete constructor method using by
serde_valid::json::FromJsonValue
trait.
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()
);
You can force validation by only deserialization through serde_valid
, and removing
serde_json
from Cargo.toml
of your project.
§Serialization
For serialization, provides serde_valid::json::ToJsonString
trait.
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()
);
§Custom Message
For user custom message, Serde Valid provides message_fn
or message
.
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 localization
fluent
feature is required.
You can also use fluent localization by using fluent
feature.
Allow the following attributes:
#[validate(..., fluent("message-id", key1 = value1, ...))]
#[validate(..., 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()
);
§Custom Validation
§Single Error Validation
You can use your custom validation using by #[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());
And you can also use closure.
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());
Custom validation is suitable for handling convenience validations not defined in JSON Schema.
serde_valid::utils::*
provides convenience functions for specific types.
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());
§Multi Errors Validation
If you want to return multiple errors in the use custom validation method, you can use #[validate(custom = ...)]
same as single error.
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());
§Multi Fields Validation
Now, you can use #[validate(custom = ...)]
for multi fields validation.
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());
§Validate Traits
By implementing the validation trait, Your original type can uses Serde Valid validations.
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());
§Validation Errors Format
§Named Struct
Field errors are output to 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()
);
§Unnamed Struct
Field errors are output to items
. The key for items
is guaranteed to be a string of positive
numbers.
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()
);
§New Type
Field errors are output to 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()
);
§Named Enum
Variant errors are output to 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()
);
§Unnamed Enum
Variant errors are output to items
. The key for items
is guaranteed to be a string of
positive numbers.
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()
);
§New Type Enum
Variant errors are output to 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()
);
Re-exports§
pub use error::EnumerateError;
pub use error::Error;
pub use error::ExclusiveMaximumError;
pub use error::ExclusiveMinimumError;
pub use error::MaxItemsError;
pub use error::MaxLengthError;
pub use error::MaxPropertiesError;
pub use error::MaximumError;
pub use error::MinItemsError;
pub use error::MinLengthError;
pub use error::MinPropertiesError;
pub use error::MinimumError;
pub use error::MultipleOfError;
pub use error::PatternError;
pub use error::UniqueItemsError;
pub use validation::ValidateEnumerate;
pub use validation::ValidateExclusiveMaximum;
pub use validation::ValidateExclusiveMinimum;
pub use validation::ValidateMaxItems;
pub use validation::ValidateMaxLength;
pub use validation::ValidateMaxProperties;
pub use validation::ValidateMaximum;
pub use validation::ValidateMinItems;
pub use validation::ValidateMinLength;
pub use validation::ValidateMinProperties;
pub use validation::ValidateMinimum;
pub use validation::ValidateMultipleOf;
pub use validation::ValidatePattern;
pub use validation::ValidateUniqueItems;