stdcode/
try_asstr.rs

1use std::{fmt::Debug, str::FromStr};
2
3use serde::Deserialize;
4use serde::{Deserializer, Serialize, Serializer};
5
6pub fn serialize<T: ToString + Serialize, S>(val: T, serializer: S) -> Result<S::Ok, S::Error>
7where
8    S: Serializer,
9{
10    if serializer.is_human_readable() {
11        serializer.serialize_str(&val.to_string())
12    } else {
13        val.serialize(serializer)
14    }
15}
16
17pub fn deserialize<'de, T: FromStr + Deserialize<'de>, D>(deserializer: D) -> Result<T, D::Error>
18where
19    D: Deserializer<'de>,
20    <T as std::str::FromStr>::Err: Debug,
21{
22    if deserializer.is_human_readable() {
23        let s = MaybeString::deserialize(deserializer)?;
24        match s {
25            MaybeString::String(s) => s
26                .parse()
27                .map_err(|e| serde::de::Error::custom(format!("FromStr parsing error {:?}", e))),
28            MaybeString::Tee(t) => Ok(t),
29        }
30    } else {
31        T::deserialize(deserializer)
32    }
33    // let s = <&str>::deserialize(deserializer)?;
34    // base64::decode(s).map_err(de::Error::custom)
35}
36
37#[derive(Serialize, Deserialize)]
38#[serde(untagged)]
39enum MaybeString<T> {
40    String(String),
41    Tee(T),
42}
43
44#[cfg(test)]
45mod tests {
46    use std::{convert::Infallible, str::FromStr};
47
48    use serde::{Deserialize, Serialize};
49
50    #[derive(Serialize, Deserialize, PartialEq, PartialOrd, Ord, Eq, Debug)]
51    struct Inner {
52        laboo: String,
53    }
54
55    impl FromStr for Inner {
56        type Err = Infallible;
57        fn from_str(s: &str) -> Result<Self, Self::Err> {
58            Ok(Self {
59                laboo: s.to_string(),
60            })
61        }
62    }
63
64    #[derive(Deserialize, PartialEq, PartialOrd, Ord, Eq, Debug)]
65    struct Test {
66        #[serde(with = "crate::try_asstr")]
67        hello: Inner,
68    }
69
70    #[test]
71    fn try_asstr() {
72        let tt: Test = serde_json::from_str(dbg!("{\"hello\": \"world\"}")).unwrap();
73        let ttt: Test = serde_json::from_str(dbg!("{\"hello\": {\"laboo\": \"world\"}}")).unwrap();
74        assert_eq!(tt, ttt)
75    }
76}