rambler-digital-solutions / actix-web-validator

Rust library for providing validation mechanism to actix-web with Validator crate.
MIT License
101 stars 26 forks source link

Error::Deserialize(DeserializeErrors::DeserializeJson) is never actually used #47

Open clechasseur opened 10 months ago

clechasseur commented 10 months ago

In my code, I created a function to allow me to write a custom error handler for JSON data validation errors. It includes something like this:

match error {
    actix_web_validator::Error::Validate(_) | actix_web_validator::Error::Deserialize(_) => Some(StatusCode::BAD_REQUEST),
    // ...more variants...
}

I was expected that any error occurring during JSON deserialization (missing field, etc.) would result in an Error::Deserialize(DeserializeErrors::DeserializeJson(_)). However, this is not the case - instead, I get an Error::JsonPayloadError(JsonPayloadError::Deserialize(_)).

I believe this is caused by this code:

https://github.com/rambler-digital-solutions/actix-web-validator/blob/b8ffc17283e6db518669849005f45a57d8f5197b/src/json.rs#L131-L134

In this match's Err(e) branch, e is an actix_web::error::JsonPayloadError. Thus, Error::from will use the From implementation for JsonPayloadError, resulting in an Error::JsonPayloadError.

I suppose one possible solution would be to add a match branch to separate the deserialization errors, something like this:

.map(|res: Result<T, _>| match res {
    Ok(data) => data.validate().map(|_| Json(data)).map_err(Error::from),
    Err(actix_web::error::JsonPayloadError::Deserialize(e)) => Err(Error::from(e)), // will use From<serde_json::error::Error for Error
    Err(e) => Err(Error::from(e)), // will use From<actix_web::error::JsonPayloadError> for Error (like before)
})

Please note that this is hypothetical, I haven't tested the above code at all. 🙂

FWIW, any deserialization error that occurs for Path or Query does result in the correct Error::Deserialize(_) variant being used.