rocket_community/serde/
json.rs

1//! Automatic JSON (de)serialization support.
2//!
3//! See [`Json`] for details.
4//!
5//! # Enabling
6//!
7//! This module is only available when the `json` feature is enabled. Enable it
8//! in `Cargo.toml` as follows:
9//!
10//! ```toml
11//! [dependencies.rocket]
12//! package = "rocket_community"
13//! version = "0.6.0"
14//! features = ["json"]
15//! ```
16//!
17//! # Testing
18//!
19//! The [`LocalRequest`] and [`LocalResponse`] types provide [`json()`] and
20//! [`into_json()`] methods to create a request with serialized JSON and
21//! deserialize a response as JSON, respectively.
22//!
23//! [`LocalRequest`]: crate::local::blocking::LocalRequest
24//! [`LocalResponse`]: crate::local::blocking::LocalResponse
25//! [`json()`]: crate::local::blocking::LocalRequest::json()
26//! [`into_json()`]: crate::local::blocking::LocalResponse::into_json()
27
28use std::ops::{Deref, DerefMut};
29use std::{error, fmt, io};
30
31use crate::data::{Data, FromData, Limits, Outcome};
32use crate::form::prelude as form;
33use crate::http::uri::fmt::{Formatter as UriFormatter, FromUriParam, Query, UriDisplay};
34use crate::http::Status;
35use crate::request::{local_cache, Request};
36use crate::response::{self, content, Responder};
37
38use serde::{Deserialize, Serialize};
39
40#[doc(hidden)]
41pub use serde_json;
42
43/// The JSON guard: easily consume and return JSON.
44///
45/// ## Sending JSON
46///
47/// To respond with serialized JSON data, return a `Json<T>` type, where `T`
48/// implements [`Serialize`] from [`serde`]. The content type of the response is
49/// set to `application/json` automatically.
50///
51/// ```rust
52/// # #[macro_use] extern crate rocket_community as rocket;
53/// # type User = usize;
54/// use rocket::serde::json::Json;
55///
56/// #[get("/users/<id>")]
57/// fn user(id: usize) -> Json<User> {
58///     let user_from_id = User::from(id);
59///     /* ... */
60///     Json(user_from_id)
61/// }
62/// ```
63///
64/// ## Receiving JSON
65///
66/// `Json` is both a data guard and a form guard.
67///
68/// ### Data Guard
69///
70/// To deserialize request body data as JSON , add a `data` route argument with
71/// a target type of `Json<T>`, where `T` is some type you'd like to parse from
72/// JSON. `T` must implement [`serde::Deserialize`].
73///
74/// ```rust
75/// # #[macro_use] extern crate rocket_community as rocket;
76/// # type User = usize;
77/// use rocket::serde::json::Json;
78///
79/// #[post("/user", format = "json", data = "<user>")]
80/// fn new_user(user: Json<User>) {
81///     /* ... */
82/// }
83/// ```
84///
85/// You don't _need_ to use `format = "json"`, but it _may_ be what you want.
86/// Using `format = json` means that any request that doesn't specify
87/// "application/json" as its `Content-Type` header value will not be routed to
88/// the handler.
89///
90/// ### Form Guard
91///
92/// `Json<T>`, as a form guard, accepts value and data fields and parses the
93/// data as a `T`. Simple use `Json<T>`:
94///
95/// ```rust
96/// # #[macro_use] extern crate rocket_community as rocket;
97/// # type Metadata = usize;
98/// use rocket::form::{Form, FromForm};
99/// use rocket::serde::json::Json;
100///
101/// #[derive(FromForm)]
102/// struct User<'r> {
103///     name: &'r str,
104///     metadata: Json<Metadata>
105/// }
106///
107/// #[post("/user", data = "<form>")]
108/// fn new_user(form: Form<User<'_>>) {
109///     /* ... */
110/// }
111/// ```
112///
113/// ### Incoming Data Limits
114///
115/// The default size limit for incoming JSON data is 1MiB. Setting a limit
116/// protects your application from denial of service (DoS) attacks and from
117/// resource exhaustion through high memory consumption. The limit can be
118/// increased by setting the `limits.json` configuration parameter. For
119/// instance, to increase the JSON limit to 5MiB for all environments, you may
120/// add the following to your `Rocket.toml`:
121///
122/// ```toml
123/// [global.limits]
124/// json = 5242880
125/// ```
126#[repr(transparent)]
127#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
128pub struct Json<T>(pub T);
129
130/// Error returned by the [`Json`] guard when JSON deserialization fails.
131#[derive(Debug)]
132pub enum Error<'a> {
133    /// An I/O error occurred while reading the incoming request data.
134    Io(io::Error),
135
136    /// The client's data was received successfully but failed to parse as valid
137    /// JSON or as the requested type. The `&str` value in `.0` is the raw data
138    /// received from the user, while the `Error` in `.1` is the deserialization
139    /// error from `serde`.
140    Parse(&'a str, serde_json::error::Error),
141}
142
143impl<'a> fmt::Display for Error<'a> {
144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145        match self {
146            Self::Io(err) => write!(f, "i/o error: {}", err),
147            Self::Parse(_, err) => write!(f, "parse error: {}", err),
148        }
149    }
150}
151
152impl<'a> error::Error for Error<'a> {
153    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
154        match self {
155            Self::Io(err) => Some(err),
156            Self::Parse(_, err) => Some(err),
157        }
158    }
159}
160
161impl<T> Json<T> {
162    /// Consumes the JSON wrapper and returns the wrapped item.
163    ///
164    /// # Example
165    /// ```rust
166    /// # extern crate rocket_community as rocket;
167    /// # use rocket::serde::json::Json;
168    /// let string = "Hello".to_string();
169    /// let my_json = Json(string);
170    /// assert_eq!(my_json.into_inner(), "Hello".to_string());
171    /// ```
172    #[inline(always)]
173    pub fn into_inner(self) -> T {
174        self.0
175    }
176}
177
178impl<'r, T: Deserialize<'r>> Json<T> {
179    fn from_str(s: &'r str) -> Result<Self, Error<'r>> {
180        serde_json::from_str(s)
181            .map(Json)
182            .map_err(|e| Error::Parse(s, e))
183    }
184
185    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Result<Self, Error<'r>> {
186        let limit = req.limits().get("json").unwrap_or(Limits::JSON);
187        let string = match data.open(limit).into_string().await {
188            Ok(s) if s.is_complete() => s.into_inner(),
189            Ok(_) => {
190                let eof = io::ErrorKind::UnexpectedEof;
191                return Err(Error::Io(io::Error::new(eof, "data limit exceeded")));
192            }
193            Err(e) => return Err(Error::Io(e)),
194        };
195
196        Self::from_str(local_cache!(req, string))
197    }
198}
199
200#[crate::async_trait]
201impl<'r, T: Deserialize<'r>> FromData<'r> for Json<T> {
202    type Error = Error<'r>;
203
204    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
205        match Self::from_data(req, data).await {
206            Ok(value) => Outcome::Success(value),
207            Err(Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
208                Outcome::Error((Status::PayloadTooLarge, Error::Io(e)))
209            }
210            Err(Error::Parse(s, e)) if e.classify() == serde_json::error::Category::Data => {
211                Outcome::Error((Status::UnprocessableEntity, Error::Parse(s, e)))
212            }
213            Err(e) => Outcome::Error((Status::BadRequest, e)),
214        }
215    }
216}
217
218/// Serializes the wrapped value into JSON. Returns a response with Content-Type
219/// JSON and a fixed-size body with the serialized value. If serialization
220/// fails, an `Err` of `Status::InternalServerError` is returned.
221impl<'r, T: Serialize> Responder<'r, 'static> for Json<T> {
222    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
223        let string = serde_json::to_string(&self.0).map_err(|e| {
224            error!("JSON serialize failure: {}", e);
225            Status::InternalServerError
226        })?;
227
228        content::RawJson(string).respond_to(req)
229    }
230}
231
232impl<T: Serialize> UriDisplay<Query> for Json<T> {
233    fn fmt(&self, f: &mut UriFormatter<'_, Query>) -> fmt::Result {
234        let string = to_string(&self.0).map_err(|_| fmt::Error)?;
235        f.write_value(&string)
236    }
237}
238
239macro_rules! impl_from_uri_param_from_inner_type {
240    ($($lt:lifetime)?, $T:ty) => (
241        impl<$($lt,)? T: Serialize> FromUriParam<Query, $T> for Json<T> {
242            type Target = Json<$T>;
243
244            #[inline(always)]
245            fn from_uri_param(param: $T) -> Self::Target {
246                Json(param)
247            }
248        }
249    )
250}
251
252impl_from_uri_param_from_inner_type!(, T);
253impl_from_uri_param_from_inner_type!('a, &'a T);
254impl_from_uri_param_from_inner_type!('a, &'a mut T);
255
256crate::http::impl_from_uri_param_identity!([Query] (T: Serialize) Json<T>);
257
258impl<T> From<T> for Json<T> {
259    fn from(value: T) -> Self {
260        Json(value)
261    }
262}
263
264impl<T> Deref for Json<T> {
265    type Target = T;
266
267    #[inline(always)]
268    fn deref(&self) -> &T {
269        &self.0
270    }
271}
272
273impl<T> DerefMut for Json<T> {
274    #[inline(always)]
275    fn deref_mut(&mut self) -> &mut T {
276        &mut self.0
277    }
278}
279
280impl From<Error<'_>> for form::Error<'_> {
281    fn from(e: Error<'_>) -> Self {
282        match e {
283            Error::Io(e) => e.into(),
284            Error::Parse(_, e) => form::Error::custom(e),
285        }
286    }
287}
288
289#[crate::async_trait]
290impl<'v, T: Deserialize<'v> + Send> form::FromFormField<'v> for Json<T> {
291    fn from_value(field: form::ValueField<'v>) -> Result<Self, form::Errors<'v>> {
292        Ok(Self::from_str(field.value)?)
293    }
294
295    async fn from_data(f: form::DataField<'v, '_>) -> Result<Self, form::Errors<'v>> {
296        Ok(Self::from_data(f.request, f.data).await?)
297    }
298}
299
300/// Serializes the value into JSON. Returns a response with Content-Type JSON
301/// and a fixed-size body with the serialized value.
302impl<'r> Responder<'r, 'static> for Value {
303    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
304        content::RawJson(self.to_string()).respond_to(req)
305    }
306}
307
308crate::export! {
309    /// A macro to create ad-hoc JSON serializable values using JSON syntax.
310    ///
311    /// The return type of a `json!` invocation is [`Value`](Value). A value
312    /// created with this macro can be returned from a handler as follows:
313    ///
314    /// ```rust
315    /// # #[macro_use] extern crate rocket_community as rocket;
316    /// use rocket::serde::json::{json, Value};
317    ///
318    /// #[get("/json")]
319    /// fn get_json() -> Value {
320    ///     json!({
321    ///         "key": "value",
322    ///         "array": [1, 2, 3, 4]
323    ///     })
324    /// }
325    /// ```
326    ///
327    /// The [`Responder`](crate::response::Responder) implementation for
328    /// `Value` serializes the value into a JSON string and sets it as the body
329    /// of the response with a `Content-Type` of `application/json`.
330    ///
331    /// # Examples
332    ///
333    /// Create a simple JSON object with two keys: `"username"` and `"id"`:
334    ///
335    /// ```rust
336    /// # extern crate rocket_community as rocket;
337    /// use rocket::serde::json::json;
338    ///
339    /// let value = json!({
340    ///     "username": "mjordan",
341    ///     "id": 23
342    /// });
343    /// ```
344    ///
345    /// Create a more complex object with a nested object and array:
346    ///
347    /// ```rust
348    /// # extern crate rocket_community as rocket;
349    /// # use rocket::serde::json::json;
350    /// let value = json!({
351    ///     "code": 200,
352    ///     "success": true,
353    ///     "payload": {
354    ///         "features": ["serde", "json"],
355    ///         "ids": [12, 121],
356    ///     },
357    /// });
358    /// ```
359    ///
360    /// Variables or expressions can be interpolated into the JSON literal. Any type
361    /// interpolated into an array element or object value must implement serde's
362    /// `Serialize` trait, while any type interpolated into a object key must
363    /// implement `Into<String>`.
364    ///
365    /// ```rust
366    /// # extern crate rocket_community as rocket;
367    /// # use rocket::serde::json::json;
368    /// let code = 200;
369    /// let features = vec!["serde", "json"];
370    ///
371    /// let value = json!({
372    ///    "code": code,
373    ///    "success": code == 200,
374    ///    "payload": {
375    ///        features[0]: features[1]
376    ///    }
377    /// });
378    /// ```
379    ///
380    /// Trailing commas are allowed inside both arrays and objects.
381    ///
382    /// ```rust
383    /// # extern crate rocket_community as rocket;
384    /// # use rocket::serde::json::json;
385    /// let value = json!([
386    ///     "notice",
387    ///     "the",
388    ///     "trailing",
389    ///     "comma -->",
390    /// ]);
391    /// ```
392    macro_rules! json {
393        ($($json:tt)+) => ($crate::serde::json::serde_json::json!($($json)*));
394    }
395}
396
397/// An arbitrary JSON value as returned by [`json!`].
398///
399/// # `Responder`
400///
401/// `Value` is a `Responder` that serializes the represented value into a JSON
402/// string and sets the string as the body of a fixed-sized response with a
403/// `Content-Type` of `application/json`.
404///
405/// # Usage
406///
407/// A value of this type is returned by [`json!`]. The macro and this type are
408/// typically used to construct JSON values in an ad-hoc fashion during request
409/// handling. This looks something like:
410///
411/// ```rust
412/// # #[macro_use] extern crate rocket_community as rocket;
413/// use rocket::serde::json::{json, Value};
414///
415/// #[get("/json")]
416/// fn get_json() -> Value {
417///     json!({
418///         "id": 83,
419///         "values": [1, 2, 3, 4]
420///     })
421/// }
422/// ```
423#[doc(inline)]
424pub use serde_json::Value;
425
426/// Deserialize an instance of type `T` from bytes of JSON text.
427///
428/// **_Always_ use [`Json`] to deserialize JSON request data.**
429///
430/// # Example
431///
432/// ```
433/// # extern crate rocket_community as rocket;
434/// use rocket::serde::{Deserialize, json};
435///
436/// #[derive(Debug, PartialEq, Deserialize)]
437/// #[serde(crate = "rocket::serde")]
438/// struct Data<'r> {
439///     framework: &'r str,
440///     stars: usize,
441/// }
442///
443/// let bytes = br#"
444///     {
445///         "framework": "Rocket",
446///         "stars": 5
447///     }
448/// "#;
449///
450/// let data: Data = json::from_slice(bytes).unwrap();
451/// assert_eq!(data, Data { framework: "Rocket", stars: 5, });
452/// ```
453///
454/// # Errors
455///
456/// This conversion can fail if the structure of the input does not match the
457/// structure expected by `T`, for example if `T` is a struct type but the input
458/// contains something other than a JSON map. It can also fail if the structure
459/// is correct but `T`'s implementation of `Deserialize` decides that something
460/// is wrong with the data, for example required struct fields are missing from
461/// the JSON map or some number is too big to fit in the expected primitive
462/// type.
463#[inline(always)]
464pub fn from_slice<'a, T>(slice: &'a [u8]) -> Result<T, serde_json::error::Error>
465where
466    T: Deserialize<'a>,
467{
468    serde_json::from_slice(slice)
469}
470
471/// Deserialize an instance of type `T` from a string of JSON text.
472///
473/// **_Always_ use [`Json`] to deserialize JSON request data.**
474///
475/// # Example
476///
477/// ```
478/// # extern crate rocket_community as rocket;
479/// use rocket::serde::{Deserialize, json};
480///
481/// #[derive(Debug, PartialEq, Deserialize)]
482/// #[serde(crate = "rocket::serde")]
483/// struct Data<'r> {
484///     framework: &'r str,
485///     stars: usize,
486/// }
487///
488/// let string = r#"
489///     {
490///         "framework": "Rocket",
491///         "stars": 5
492///     }
493/// "#;
494///
495/// let data: Data = json::from_str(string).unwrap();
496/// assert_eq!(data, Data { framework: "Rocket", stars: 5, });
497/// ```
498///
499/// # Errors
500///
501/// This conversion can fail if the structure of the input does not match the
502/// structure expected by `T`, for example if `T` is a struct type but the input
503/// contains something other than a JSON map. It can also fail if the structure
504/// is correct but `T`'s implementation of `Deserialize` decides that something
505/// is wrong with the data, for example required struct fields are missing from
506/// the JSON map or some number is too big to fit in the expected primitive
507/// type.
508#[inline(always)]
509pub fn from_str<'a, T>(string: &'a str) -> Result<T, serde_json::error::Error>
510where
511    T: Deserialize<'a>,
512{
513    serde_json::from_str(string)
514}
515
516/// Serialize a `T` into a JSON string with compact representation.
517///
518/// **_Always_ use [`Json`] to serialize JSON response data.**
519///
520/// # Example
521///
522/// ```
523/// # extern crate rocket_community as rocket;
524/// use rocket::serde::{Deserialize, Serialize, json};
525///
526/// #[derive(Debug, PartialEq, Deserialize, Serialize)]
527/// #[serde(crate = "rocket::serde")]
528/// struct Data<'r> {
529///     framework: &'r str,
530///     stars: usize,
531/// }
532///
533/// let data = Data {
534///     framework: "Rocket",
535///     stars: 5,
536/// };
537///
538/// let string = json::to_string(&data).unwrap();
539/// let data: Data = json::from_str(&string).unwrap();
540/// assert_eq!(data, Data { framework: "Rocket", stars: 5, });
541/// ```
542///
543/// # Errors
544///
545/// Serialization fails if `T`'s `Serialize` implementation fails or if `T`
546/// contains a map with non-string keys.
547#[inline(always)]
548pub fn to_string<T>(value: &T) -> Result<String, serde_json::error::Error>
549where
550    T: Serialize,
551{
552    serde_json::to_string(value)
553}
554
555/// Serialize a `T` into a JSON string with "pretty" formatted representation.
556///
557/// **_Always_ use [`Json`] to serialize JSON response data.**
558///
559/// # Example
560///
561/// ```
562/// # extern crate rocket_community as rocket;
563/// use rocket::serde::{Deserialize, Serialize, json};
564///
565/// #[derive(Debug, PartialEq, Deserialize, Serialize)]
566/// #[serde(crate = "rocket::serde")]
567/// struct Data<'r> {
568///     framework: &'r str,
569///     stars: usize,
570/// }
571///
572/// let data = Data {
573///     framework: "Rocket",
574///     stars: 5,
575/// };
576///
577/// let string = json::to_pretty_string(&data).unwrap();
578/// # let compact = json::to_string(&data).unwrap();
579/// # assert_ne!(compact, string);
580/// let data: Data = json::from_str(&string).unwrap();
581/// assert_eq!(data, Data { framework: "Rocket", stars: 5, });
582/// ```
583///
584/// # Errors
585///
586/// Serialization fails if `T`'s `Serialize` implementation fails or if `T`
587/// contains a map with non-string keys.
588#[inline(always)]
589pub fn to_pretty_string<T>(value: &T) -> Result<String, serde_json::error::Error>
590where
591    T: Serialize,
592{
593    serde_json::to_string_pretty(value)
594}
595
596/// Interpret a [`Value`] as an instance of type `T`.
597///
598/// # Example
599///
600/// ```
601/// # extern crate rocket_community as rocket;
602/// use rocket::serde::{Deserialize, json};
603///
604/// #[derive(Debug, PartialEq, Deserialize)]
605/// #[serde(crate = "rocket::serde")]
606/// struct Data {
607///     framework: String ,
608///     stars: usize,
609/// }
610///
611/// let value = json::json!({
612///     "framework": "Rocket",
613///     "stars": 5
614/// });
615///
616/// let data: Data = json::from_value(value).unwrap();
617/// assert_eq!(data, Data { framework: "Rocket".into(), stars: 5, });
618/// ```
619///
620/// # Errors
621///
622/// This conversion can fail if the structure of the input does not match the
623/// structure expected by `T`, for example if `T` is a struct type but the input
624/// contains something other than a JSON map. It can also fail if the structure
625/// is correct but `T`'s implementation of `Deserialize` decides that something
626/// is wrong with the data, for example required struct fields are missing from
627/// the JSON map or some number is too big to fit in the expected primitive
628/// type.
629#[inline(always)]
630pub fn from_value<T>(value: Value) -> Result<T, serde_json::error::Error>
631where
632    T: crate::serde::DeserializeOwned,
633{
634    serde_json::from_value(value)
635}
636
637/// Convert a `T` into a [`Value`], an opaque value representing JSON data.
638///
639/// # Example
640///
641/// ```
642/// # extern crate rocket_community as rocket;
643/// use rocket::serde::{Deserialize, Serialize, json};
644///
645/// #[derive(Deserialize, Serialize)]
646/// #[serde(crate = "rocket::serde")]
647/// struct Data {
648///     framework: String ,
649///     stars: usize,
650/// }
651///
652/// let value = json::json!({
653///     "framework": "Rocket",
654///     "stars": 5
655/// });
656///
657/// let data: Data = json::from_value(value.clone()).unwrap();
658/// let data_value = json::to_value(data).unwrap();
659/// assert_eq!(value, data_value);
660/// ```
661///
662/// # Errors
663///
664/// This conversion fails if `T`’s implementation of `Serialize` decides to fail
665/// or if `T` contains a map with non-string keys.
666#[inline(always)]
667pub fn to_value<T>(item: T) -> Result<Value, serde_json::error::Error>
668where
669    T: Serialize,
670{
671    serde_json::to_value(item)
672}