Skip to main content

rama_http/service/web/endpoint/response/
json.rs

1use super::IntoResponse;
2use crate::headers::ContentType;
3use crate::{Body, Response, StatusCode};
4use rama_core::bytes::{BufMut, BytesMut};
5use rama_core::error::BoxError;
6use rama_utils::macros::impl_deref;
7use serde::Serialize;
8
9use super::Headers;
10
11/// Wrapper used to create Json Http [`Response`]s,
12/// as well as to extract Json from Http [`Request`] bodies.
13///
14/// [`Request`]: crate::Request
15/// [`Response`]: crate::Response
16///
17/// # Examples
18///
19/// ## Creating a Json Response
20///
21/// ```
22/// use serde_json::json;
23/// use rama_http::service::web::response::{IntoResponse, Json};
24///
25/// async fn handler() -> impl IntoResponse {
26///     Json(json!({
27///         "name": "john",
28///         "age": 30,
29///         "is_student": false
30///     }))
31/// }
32/// ```
33///
34/// ## Extracting Json from a Request
35///
36/// ```
37/// use serde_json::json;
38/// use rama_http::service::web::response::Json;
39///
40/// #[derive(Debug, serde::Deserialize)]
41/// struct Input {
42///     name: String,
43///     age: u8,
44///     alive: Option<bool>,
45/// }
46///
47/// # fn bury(name: impl AsRef<str>) {}
48///
49/// async fn handler(Json(input): Json<Input>) {
50///     if !input.alive.unwrap_or_default() {
51///         bury(&input.name);
52///     }
53/// }
54/// ```
55#[derive(Debug, Clone)]
56pub struct Json<T>(pub T);
57
58impl_deref!(Json);
59
60impl<T> From<T> for Json<T> {
61    fn from(inner: T) -> Self {
62        Self(inner)
63    }
64}
65
66impl<T> IntoResponse for Json<T>
67where
68    T: Serialize,
69{
70    fn into_response(self) -> Response {
71        // Extracted into separate fn so it's only compiled once for all T.
72        fn make_response(buf: BytesMut, ser_result: serde_json::Result<()>) -> Response {
73            match ser_result {
74                Ok(()) => (Headers::single(ContentType::json()), buf.freeze()).into_response(),
75                Err(err) => (
76                    StatusCode::INTERNAL_SERVER_ERROR,
77                    Headers::single(ContentType::text_utf8()),
78                    err.to_string(),
79                )
80                    .into_response(),
81            }
82        }
83        // Use a small initial capacity of 128 bytes like serde_json::to_vec
84        // https://docs.rs/serde_json/1.0.82/src/serde_json/ser.rs.html#2189
85        let mut buf = BytesMut::with_capacity(128).writer();
86        let res = serde_json::to_writer(&mut buf, &self.0);
87        make_response(buf.into_inner(), res)
88    }
89}
90
91impl<T> TryFrom<Json<T>> for Body
92where
93    T: Serialize,
94{
95    type Error = BoxError;
96
97    fn try_from(json: Json<T>) -> Result<Self, Self::Error> {
98        // Use a small initial capacity of 128 bytes like serde_json::to_vec
99        // https://docs.rs/serde_json/1.0.82/src/serde_json/ser.rs.html#2189
100        let mut buf = BytesMut::with_capacity(128).writer();
101        match serde_json::to_writer(&mut buf, &json.0) {
102            Ok(()) => Ok(buf.into_inner().freeze().into()),
103            Err(err) => Err(BoxError::from(err)),
104        }
105    }
106}