axum_bootstrap/util/
json.rs

1use std::fmt::Display;
2use std::str::FromStr;
3use std::{borrow::Cow, fmt};
4
5use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
6
7/// Serde deserialization decorator to map empty Strings to None,
8#[allow(dead_code)]
9fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error>
10where
11    D: Deserializer<'de>,
12    T: FromStr,
13    T::Err: fmt::Display,
14{
15    let opt = Option::<String>::deserialize(de)?;
16    match opt.as_deref() {
17        None | Some("") => Ok(None),
18        Some(s) => FromStr::from_str(s).map_err(de::Error::custom).map(Some),
19    }
20}
21
22#[derive(Debug, Clone, Default, PartialEq, Eq)]
23pub struct StupidValue<T>(pub T);
24
25impl<T> Serialize for StupidValue<T>
26where
27    T: ToString,
28{
29    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
30    where
31        S: Serializer,
32    {
33        self.0.to_string().serialize(serializer)
34    }
35}
36
37impl<'de, T> Deserialize<'de> for StupidValue<T>
38where
39    T: FromStr + Deserialize<'de>,
40    T::Err: Display,
41{
42    fn deserialize<D>(deserializer: D) -> Result<StupidValue<T>, D::Error>
43    where
44        D: Deserializer<'de>,
45    {
46        #[derive(Deserialize)]
47        #[serde(untagged)]
48        enum StrOrValue<'a, T> {
49            Str(Cow<'a, str>),
50            Value(T),
51        }
52
53        let str_or_val = StrOrValue::<T>::deserialize(deserializer)?;
54        Ok(StupidValue(match str_or_val {
55            StrOrValue::Value(val) => val,
56            StrOrValue::Str(s) => s.parse().map_err(serde::de::Error::custom)?,
57        }))
58    }
59}
60
61impl<T> From<T> for StupidValue<T> {
62    fn from(val: T) -> Self {
63        StupidValue(val)
64    }
65}
66
67pub mod my_date_format {
68    use chrono::NaiveDateTime;
69    use serde::{self, Deserialize, Deserializer, Serializer};
70
71    const FORMAT: &str = "%Y-%m-%d %H:%M:%S";
72
73    pub fn serialize<S>(date: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
74    where
75        S: Serializer,
76    {
77        let s = format!("{}", date.format(FORMAT));
78        serializer.serialize_str(&s)
79    }
80
81    pub fn deserialize<'de, D>(deserializer: D) -> Result<NaiveDateTime, D::Error>
82    where
83        D: Deserializer<'de>,
84    {
85        let s = String::deserialize(deserializer)?;
86        let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?;
87        Ok(dt)
88    }
89}
90
91pub mod my_date_format_option {
92    use super::my_date_format;
93    use chrono::NaiveDateTime;
94    use serde::{self, Deserialize, Deserializer, Serializer};
95
96    const FORMAT: &str = "%Y-%m-%d %H:%M:%S";
97
98    pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
99    where
100        S: Serializer,
101    {
102        match *opt {
103            Some(ref dt) => my_date_format::serialize(dt, serializer),
104            None => serializer.serialize_none(),
105        }
106    }
107
108    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDateTime>, D::Error>
109    where
110        D: Deserializer<'de>,
111    {
112        match Option::<String>::deserialize(deserializer)? {
113            Some(s) => {
114                let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?;
115                Ok(Some(dt))
116            }
117            None => Ok(None),
118        }
119    }
120}