actix-web-validator 7.0.0

Validation mechanism for actix-web
Documentation
use actix_web_validator::{error::DeserializeErrors, Error};
use serde::{Deserialize, Serialize};
use validator::{Validate, ValidationErrorsKind};

#[derive(Deserialize)]
#[allow(dead_code)]
struct Query {
    test: i32,
    value: i32,
}

#[test]
fn test_serde_urlencoded_error_transformation() {
    let error = serde_urlencoded::from_str::<Query>("test=42&value=[").map_err(Error::from);
    assert!(matches!(
        error,
        Err(Error::Deserialize(DeserializeErrors::DeserializeQuery(_)))
    ));
}

#[test]
fn test_serde_json_error_transformation() {
    let error =
        serde_json::from_str::<Query>("{\"test\": 42, \"value\": null}").map_err(Error::from);
    assert!(matches!(
        error,
        Err(Error::Deserialize(DeserializeErrors::DeserializeJson(_)))
    ));
}

#[derive(Serialize, Deserialize, Validate, Debug)]
#[serde(rename_all = "camelCase")]
pub struct SearchParams {
    #[validate(nested)]
    page_params: PageParams,
    #[validate(url)]
    redirect_results: String,
}

#[derive(Serialize, Deserialize, Validate, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PageParams {
    #[validate(range(min = 1))]
    page: u16,
    #[validate(range(min = 1, max = 100))]
    page_size: u8,
}

macro_rules! cast {
    ($target: expr, $pat: path) => {{
        if let $pat(a) = $target {
            a
        } else {
            panic!("mismatch variant when cast to {}", stringify!($pat));
        }
    }};
}

#[test]
fn test_flatten_error() {
    let params = serde_json::from_str::<SearchParams>(
        "{\"pageParams\":{\"page\":0,\"pageSize\":101},\"redirectResults\":\"invalid url\"}",
    )
    .map_err(crate::Error::from)
    .expect("invalid json");
    let validation = params.validate().unwrap_err();
    let errors = actix_web_validator::error::flatten_errors(&validation);
    assert_eq!(
        (
            &1u16,
            &cast!(
                &validation.errors().get("page_params").unwrap(),
                ValidationErrorsKind::Struct
            )
            .field_errors()
            .get("page_size")
            .unwrap()[0]
        ),
        errors
            .iter()
            .find(|(_, field, _)| field == "page_params.page_size")
            .map(|(indent, _, e)| (indent, *e))
            .unwrap()
    );
    assert_eq!(
        (
            &0u16,
            &validation.field_errors().get("redirect_results").unwrap()[0]
        ),
        errors
            .iter()
            .find(|(_, field, _)| field == "redirect_results")
            .map(|(indent, _, e)| (indent, *e))
            .unwrap()
    );
}