rust 57 lines · 7 steps

A validating JSON extractor in Axum

Wrap Axum's Json extractor so request bodies are both deserialized and validated before your handler runs.

Explained by highlit
1use axum::{
2 async_trait,
3 extract::{rejection::JsonRejection, FromRequest, Request},
4 http::StatusCode,
5 response::{IntoResponse, Response},
6 Json,
7};
8use serde::de::DeserializeOwned;
9use serde_json::json;
10use validator::Validate;
11 
12pub struct ValidatedJson<T>(pub T);
13 
14#[async_trait]
15impl<T, S> FromRequest<S> for ValidatedJson<T>
16where
17 T: DeserializeOwned + Validate,
18 S: Send + Sync,
19{
20 type Rejection = ValidationRejection;
21 
22 async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
23 let Json(value) = Json::<T>::from_request(req, state).await?;
24 value.validate()?;
25 Ok(ValidatedJson(value))
26 }
27}
28 
29pub enum ValidationRejection {
30 Json(JsonRejection),
31 Invalid(validator::ValidationErrors),
32}
33 
34impl From<JsonRejection> for ValidationRejection {
35 fn from(rejection: JsonRejection) -> Self {
36 Self::Json(rejection)
37 }
38}
39 
40impl From<validator::ValidationErrors> for ValidationRejection {
41 fn from(errors: validator::ValidationErrors) -> Self {
42 Self::Invalid(errors)
43 }
44}
45 
46impl IntoResponse for ValidationRejection {
47 fn into_response(self) -> Response {
48 match self {
49 Self::Json(rejection) => rejection.into_response(),
50 Self::Invalid(errors) => (
51 StatusCode::UNPROCESSABLE_ENTITY,
52 Json(json!({ "message": "validation failed", "errors": errors })),
53 )
54 .into_response(),
55 }
56 }
57}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Implementing FromRequest lets you build custom extractors that run logic before a handler ever executes.
  2. 2Composing an existing extractor inside your own keeps deserialization concerns separate from validation.
  3. 3A dedicated rejection type with IntoResponse gives each failure mode its own tailored HTTP response.

Related explainers

Share this explainer

Here's the card — post it anywhere.

A validating JSON extractor in Axum — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code