Skip to main content

rws_http/json/
extractor.rs

1//! Serde-based JSON extractor and responder (`serde` feature).
2
3#[cfg(test)]
4mod tests;
5
6use serde::{de::DeserializeOwned, Serialize};
7
8use crate::core::New;
9use crate::error::{AppError, IntoResponse};
10use crate::extract::FromRequest;
11use crate::mime_type::MimeType;
12use crate::range::Range;
13use crate::request::Request;
14use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
15
16/// A JSON extractor and responder backed by `serde_json`.
17///
18/// Wrap a [`Deserialize`][serde::Deserialize] type to extract JSON from a
19/// request body, or wrap a [`Serialize`][serde::Serialize] type to produce
20/// a `200 OK application/json` response.
21///
22/// # Deserializing (request → typed struct)
23///
24/// ```rust,no_run
25/// # extern crate rws_http as rust_web_server;
26/// use serde::Deserialize;
27/// use rust_web_server::json::Json;
28/// use rust_web_server::request::Request;
29///
30/// #[derive(Deserialize)]
31/// struct CreateUser { name: String, age: u32 }
32///
33/// fn handler(req: &Request) -> Result<(), rust_web_server::response::Response> {
34///     let Json(payload) = Json::<CreateUser>::from_request(req)?;
35///     // payload.name, payload.age
36///     Ok(())
37/// }
38/// ```
39///
40/// # Serializing (typed struct → response)
41///
42/// ```rust,no_run
43/// # extern crate rws_http as rust_web_server;
44/// use serde::Serialize;
45/// use rust_web_server::json::Json;
46///
47/// #[derive(Serialize)]
48/// struct UserResponse { id: u64, name: String }
49///
50/// let response = Json(UserResponse { id: 1, name: "Alice".into() }).into_response();
51/// ```
52#[derive(Debug)]
53pub struct Json<T>(pub T);
54
55impl<T> std::ops::Deref for Json<T> {
56    type Target = T;
57    fn deref(&self) -> &T {
58        &self.0
59    }
60}
61
62impl<T> std::ops::DerefMut for Json<T> {
63    fn deref_mut(&mut self) -> &mut T {
64        &mut self.0
65    }
66}
67
68impl<T: DeserializeOwned> Json<T> {
69    /// Deserialize `T` from the request body as JSON.
70    ///
71    /// Returns a `400 Bad Request` response on parse failure.
72    pub fn from_request(request: &Request) -> Result<Json<T>, Response> {
73        serde_json::from_slice(&request.body)
74            .map(Json)
75            .map_err(|e| AppError::BadRequest(e.to_string()).into_response())
76    }
77}
78
79impl<T: DeserializeOwned> FromRequest for Json<T> {
80    fn from_request(request: &Request) -> Result<Self, Response> {
81        Json::from_request(request)
82    }
83}
84
85impl<T: Serialize> Json<T> {
86    /// Serialize `T` as JSON and return a `200 OK` response with
87    /// `Content-Type: application/json`.
88    ///
89    /// Returns `500 Internal Server Error` if serialization fails (rare for
90    /// well-formed `Serialize` implementations).
91    pub fn into_response(self) -> Response {
92        match serde_json::to_vec(&self.0) {
93            Ok(body) => {
94                let mut response = Response::new();
95                response.status_code = *STATUS_CODE_REASON_PHRASE.n200_ok.status_code;
96                response.reason_phrase =
97                    STATUS_CODE_REASON_PHRASE.n200_ok.reason_phrase.to_string();
98                response.content_range_list = vec![Range::get_content_range(
99                    body,
100                    MimeType::APPLICATION_JSON.to_string(),
101                )];
102                response
103            }
104            Err(e) => AppError::Internal(e.to_string()).into_response(),
105        }
106    }
107}
108
109/// A handler may return `Json<T>` (18.28.0): `200 OK`, `application/json`.
110impl<T: Serialize> IntoResponse for Json<T> {
111    fn into_response(self) -> Response {
112        Json::<T>::into_response(self)
113    }
114}