Crate serde_valid
source ·Expand description
Serde Valid
This is JSON Schema based validation tool using with serde.
Usage
You derive Validate trait, and write validations.
use serde_valid::Validate;
#[derive(Validate)]
struct SampleStruct {
#[validate(minimum = 0)]
#[validate(maximum = 10)]
val: i32,
}
#[derive(Validate)]
enum SampleEnum {
Named {
#[validate]
a: SampleStruct,
},
}
let s = SampleEnum::Named {
a: SampleStruct { val: 5 },
};
assert!(s.validate().is_ok());Feature Flags
toml- provide serialization/deserialization intomlformat.yaml- provide serialization/deserialization inyamlformat.i128- supporti128/u128type.flatten- change formatting to flattened error messages ( jsonschema crate style).
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 |
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 SampleStruct {
#[validate(maximum = 100)]
val: i32,
}
// Deserialization and Validation!! 🚀
let err = SampleStruct::from_json_value(json!({ "val": 123 })).unwrap_err();
assert_eq!(
err.as_validation_errors().unwrap().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 SampleStruct {
#[validate(maximum = 100)]
val: i32,
}
assert_eq!(
SampleStruct{ 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 min custom message_fn.".to_string()
}
#[derive(Validate)]
struct SampleStruct {
#[validate(min_items = 4, message_fn(min_error_message))]
#[validate(max_items = 2, message = "this is max custom message.")]
val: Vec<i32>,
}
let s = SampleStruct { val: vec![1, 2, 3] };
assert_eq!(
s.validate().unwrap_err().to_string(),
json!({
"errors": [],
"properties": {
"val": {
"errors": [
"this is min custom message_fn.",
"this is max custom message."
]
}
}
})
.to_string()
);Custom method
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 SampleStruct {
#[validate(custom(user_validation))]
val: i32,
}
let s = SampleStruct { val: 1 };
assert!(s.validate().is_ok());Rules
If you want to check multi fields validation, can use #[rule].
use serde_json::json;
use serde_valid::Validate;
fn sample_rule(_val1: &i32, _val2: &str) -> Result<(), serde_valid::validation::Error> {
Err(serde_valid::validation::Error::Custom(
"Rule error.".to_owned(),
))
}
#[derive(Validate)]
#[rule(sample_rule(val2, val1))]
struct SampleStruct {
val1: String,
val2: i32,
}
let s = SampleStruct {
val1: "val1".to_owned(),
val2: 1,
};
let errors = s.validate().unwrap_err();
assert_eq!(
errors.to_string(),
json!({
"errors": ["Rule error."],
"properties": {}
})
.to_string()
);If you want to use rule to unnamed fields struct, just like this,
use serde_json::json;
use serde_valid::Validate;
fn sample_rule(_val1: &i32, _val2: &str) -> Result<(), serde_valid::validation::Error> {
Ok(())
}
#[derive(Validate)]
#[rule(sample_rule(0, 1))]
struct SampleStruct(i32, String);
let s = SampleStruct(0, "1".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 SampleStruct {
#[validate(max_length = 5)]
val: MyType,
}
let s = SampleStruct {
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 SampleStruct {
#[validate(maximum = 4)]
val: u32,
}
let s = SampleStruct { 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 SampleStruct (
#[validate(maximum = 4)] u32,
#[validate(maximum = 3)] u32,
);
let s = SampleStruct ( 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 SampleStruct (
#[validate(maximum = 4)] u32
);
let s = SampleStruct (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 SampleEnum {
Named {
#[validate(maximum = 5)]
a: i32,
#[validate(maximum = 5)]
b: i32,
},
}
let s = SampleEnum::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 SampleEnum {
Unnamed (
#[validate(maximum = 5)] i32,
#[validate(maximum = 5)] i32,
),
}
let s = SampleEnum::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()
);Newtype Enum
Variant errors are output to errors.
use serde_json::json;
use serde_valid::Validate;
#[derive(Validate)]
enum SampleEnum {
NewType (
#[validate(maximum = 5)] i32,
),
}
let s = SampleEnum::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;