serde_with/de/
mod.rs

1//! Module for [`DeserializeAs`][] implementations
2//!
3//! The module contains the [`DeserializeAs`][] trait and helper code.
4//! Additionally, it contains implementations of [`DeserializeAs`][] for types defined in the Rust Standard Library or this crate.
5//!
6//! You can find more details on how to implement this trait for your types in the documentation of the [`DeserializeAs`][] trait and details about the usage in the [user guide][].
7//!
8//! [user guide]: crate::guide
9
10#[cfg(feature = "alloc")]
11mod duplicates;
12mod impls;
13#[cfg(feature = "alloc")]
14mod skip_error;
15
16use crate::prelude::*;
17
18/// A **data structure** that can be deserialized from any data format supported by Serde, analogue to [`Deserialize`].
19///
20/// The trait is analogue to the [`serde::Deserialize`][`Deserialize`] trait, with the same meaning of input and output arguments.
21/// It can and should be implemented using the same code structure as the [`Deserialize`] trait.
22/// As such, the same advice for [implementing `Deserialize`][impl-deserialize] applies here.
23///
24/// # Differences to [`Deserialize`]
25///
26/// The trait is only required for container-like types or types implementing specific conversion functions.
27/// Container-like types are [`Vec`], [`BTreeMap`], but also [`Option`] and [`Box`].
28/// Conversion types deserialize into a different Rust type.
29/// For example, [`DisplayFromStr`] uses the [`FromStr`] trait after deserializing a string and [`DurationSeconds`] creates a [`Duration`] from either String or integer values.
30///
31/// This code shows how to implement [`Deserialize`] for [`Box`]:
32///
33/// ```rust,ignore
34/// impl<'de, T: Deserialize<'de>> Deserialize<'de> for Box<T> {
35///     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
36///     where
37///         D: Deserializer<'de>,
38///     {
39///         Ok(Box::new(Deserialize::deserialize(deserializer)?))
40///     }
41/// }
42/// ```
43///
44/// and this code shows how to do the same using [`DeserializeAs`][]:
45///
46/// ```rust,ignore
47/// impl<'de, T, U> DeserializeAs<'de, Box<T>> for Box<U>
48/// where
49///     U: DeserializeAs<'de, T>,
50/// {
51///     fn deserialize_as<D>(deserializer: D) -> Result<Box<T>, D::Error>
52///     where
53///         D: Deserializer<'de>,
54///     {
55///         Ok(Box::new(
56///             DeserializeAsWrap::<T, U>::deserialize(deserializer)?.into_inner(),
57///         ))
58///     }
59/// }
60/// ```
61///
62/// It uses two type parameters, `T` and `U` instead of only one and performs the deserialization step using the `DeserializeAsWrap` type.
63/// The `T` type is the type on the Rust side after deserialization, whereas the `U` type determines how the value will be deserialized.
64/// These two changes are usually enough to make a container type implement [`DeserializeAs`][].
65///
66///
67/// [`DeserializeAsWrap`] is a piece of glue code which turns [`DeserializeAs`] into a serde compatible datatype, by converting all calls to `deserialize` into `deserialize_as`.
68/// This allows us to implement [`DeserializeAs`] such that it can be applied recursively throughout the whole data structure.
69/// This is mostly important for container types, such as `Vec` or `BTreeMap`.
70/// In a `BTreeMap` this allows us to specify two different serialization behaviors, one for key and one for value, using the [`DeserializeAs`] trait.
71///
72/// ## Implementing a converter Type
73///
74/// This shows a simplified implementation for [`DisplayFromStr`].
75///
76/// ```rust
77/// # #[cfg(feature = "macros")] {
78/// # use serde::Deserialize;
79/// # use serde::de::Error;
80/// # use serde_with::{serde_as, DeserializeAs};
81/// # use std::str::FromStr;
82/// # use std::fmt::Display;
83/// struct DisplayFromStr;
84///
85/// impl<'de, T> DeserializeAs<'de, T> for DisplayFromStr
86/// where
87///     T: FromStr,
88///     T::Err: Display,
89/// {
90///     fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
91///     where
92///         D: serde::Deserializer<'de>,
93///     {
94///         let s = String::deserialize(deserializer).map_err(Error::custom)?;
95///         s.parse().map_err(Error::custom)
96///     }
97/// }
98/// #
99/// # #[serde_as]
100/// # #[derive(serde::Deserialize)]
101/// # struct S (#[serde_as(as = "DisplayFromStr")] bool);
102/// #
103/// # assert!(!serde_json::from_str::<S>(r#""false""#).unwrap().0);
104/// # }
105/// ```
106/// [`Box`]: std::boxed::Box
107/// [`BTreeMap`]: std::collections::BTreeMap
108/// [`Duration`]: std::time::Duration
109/// [`FromStr`]: std::str::FromStr
110/// [`Vec`]: std::vec::Vec
111/// [impl-deserialize]: https://serde.rs/impl-deserialize.html
112pub trait DeserializeAs<'de, T>: Sized {
113    /// Deserialize this value from the given Serde deserializer.
114    fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
115    where
116        D: Deserializer<'de>;
117}
118
119/// Helper type to implement [`DeserializeAs`] for container-like types.
120pub struct DeserializeAsWrap<T, U> {
121    value: T,
122    marker: PhantomData<U>,
123}
124
125impl<T, U> DeserializeAsWrap<T, U> {
126    /// Return the inner value of type `T`.
127    pub fn into_inner(self) -> T {
128        self.value
129    }
130}
131
132impl<'de, T, U> Deserialize<'de> for DeserializeAsWrap<T, U>
133where
134    U: DeserializeAs<'de, T>,
135{
136    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
137    where
138        D: Deserializer<'de>,
139    {
140        U::deserialize_as(deserializer).map(|value| Self {
141            value,
142            marker: PhantomData,
143        })
144    }
145}
146
147impl<T: ?Sized> As<T> {
148    /// Deserialize type `T` using [`DeserializeAs`][]
149    ///
150    /// The function signature is compatible with [serde's `with` annotation][with-annotation].
151    ///
152    /// [with-annotation]: https://serde.rs/field-attrs.html#with
153    pub fn deserialize<'de, D, I>(deserializer: D) -> Result<I, D::Error>
154    where
155        T: DeserializeAs<'de, I>,
156        D: Deserializer<'de>,
157    {
158        T::deserialize_as(deserializer)
159    }
160}