ferrox_validation/
extractor.rs1use axum::{
2 async_trait,
3 extract::{FromRequest, Request, rejection::JsonRejection},
4 Json,
5};
6use serde::de::DeserializeOwned;
7use validator::Validate;
8use ferrox_errors::AppError;
9
10#[derive(Debug, Clone, Copy, Default)]
14pub struct ValidatedJson<T>(pub T);
15
16#[async_trait]
17impl<T, S> FromRequest<S> for ValidatedJson<T>
18where
19 T: DeserializeOwned + Validate,
20 S: Send + Sync,
21 Json<T>: FromRequest<S, Rejection = JsonRejection>,
22{
23 type Rejection = AppError;
24
25 async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
26 let Json(value) = Json::<T>::from_request(req, state)
29 .await
30 .map_err(|err| AppError::ValidationError(format!("Invalid JSON payload: {}", err)))?;
31
32 value.validate().map_err(|err| {
35 AppError::ValidationError(format!("Validation failed: {}", err))
37 })?;
38
39 Ok(ValidatedJson(value))
41 }
42}