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 }
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}