Serde Valid

Latest Version GitHub license

This is JSON Schema based validation tool using with serde.

Usage

You derive Validate trait, and write validations.

```rust 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()); ```

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.

```rust use serde::Deserialize; use serdevalid::Validate; use serdevalid::json::{json, FromJsonValue};

[derive(Debug, Deserialize, Validate)]

struct SampleStruct { #[validate(maximum = 100)] val: i32, }

// Deserialization and Validation!! πŸš€ let err = SampleStruct::fromjsonvalue(json!({ "val": 123 })).unwrap_err();

asserteq!( err.asvalidationerrors().unwrap().tostring(), 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.

```rust use serde::Serialize; use serdevalid::Validate; use serdevalid::json::{json, ToJsonString};

[derive(Debug, Serialize, Validate)]

struct SampleStruct { #[validate(maximum = 100)] val: i32, }

asserteq!( SampleStruct{ val: 12i32 }.tojsonstring().unwrap(), json!({ "val": 12i32 }).tojson_string().unwrap() ); ```

Custom Message

For user custom message, Serde Valid provides message_fn or message.

```rust use serdejson::json; use serdevalid::Validate;

[inline]

fn minerrormessage(params: &serdevalid::MinItemsErrorParams) -> String { "this is min custom messagefn.".tostring() }

[derive(Validate)]

struct SampleStruct { #[validate(minitems = 4, messagefn(minerrormessage))] #[validate(max_items = 2, message = "this is max custom message.")] val: Vec, }

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

asserteq!( s.validate().unwraperr().tostring(), json!({ "errors": [], "properties": { "val": { "errors": [ "this is min custom messagefn.", "this is max custom message." ] } } }) .to_string() ); ```

Custom method

You can use your custom validation using by #[validate(custom)].

```rust use serde_valid::Validate;

fn uservalidation(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].

```rust use serdejson::json; use serdevalid::Validate;

fn samplerule(val1: &i32, val2: &str) -> Result<(), serdevalid::validation::Error> { Err(serdevalid::validation::Error::Custom( "Rule error.".toowned(), )) }

[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();

asserteq!( errors.tostring(), json!({ "errors": ["Rule error."], "properties": {} }) .to_string() ); ```

If you want to use rule to unnamed fields struct, just like this,

```rust use serdejson::json; use serdevalid::Validate;

fn samplerule(val1: &i32, val2: &str) -> Result<(), serdevalid::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.

```rust use serde_valid::Validate;

struct MyType(String);

impl serdevalid::ValidateMaxLength for MyType { fn validatemaxlength(&self, maxlength: usize) -> Result<(), serdevalid::MaxLengthErrorParams> { self.0.validatemaxlength(maxlength) } }

[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.

```rust use serdejson::json; use serdevalid::Validate;

[derive(Validate)]

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

let s = SampleStruct { val: 5 };

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

Unnamed Struct

Field errors are output to items. The key for items is guaranteed to be a string of positive numbers.

```rust use serdejson::json; use serdevalid::Validate;

[derive(Validate)]

struct SampleStruct ( #[validate(maximum = 4)] u32, #[validate(maximum = 3)] u32, );

let s = SampleStruct ( 5, 4 );

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

New Type

Field errors are output to errors.

```rust use serdejson::json; use serdevalid::Validate;

[derive(Validate)]

struct SampleStruct ( #[validate(maximum = 4)] u32 );

let s = SampleStruct (5);

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

Named Enum

Variant errors are output to properties.

```rust use serdejson::json; use serdevalid::Validate;

[derive(Validate)]

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

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

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

Unnamed Enum

Variant errors are output to items. The key for items is guaranteed to be a string of positive numbers.

```rust use serdejson::json; use serdevalid::Validate;

[derive(Validate)]

enum SampleEnum { Unnamed ( #[validate(maximum = 5)] i32, #[validate(maximum = 5)] i32, ), }

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

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

Newtype Enum

Variant errors are output to errors.

```rust use serdejson::json; use serdevalid::Validate;

[derive(Validate)]

enum SampleEnum { NewType ( #[validate(maximum = 5)] i32, ), }

let s = SampleEnum::NewType ( 6 );

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