1 #![allow(clippy::trait_duplication_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/8757
2
3 use serde::{Deserialize, Deserializer};
4 use std::fmt::{self, Display};
5 use std::marker::PhantomData;
6 use std::str::FromStr;
7
8 pub struct NumberVisitor<T> {
9 marker: PhantomData<T>,
10 }
11
12 impl<'de, T> serde::de::Visitor<'de> for NumberVisitor<T>
13 where
14 T: TryFrom<u64> + TryFrom<i64> + FromStr,
15 <T as TryFrom<u64>>::Error: Display,
16 <T as TryFrom<i64>>::Error: Display,
17 <T as FromStr>::Err: Display,
18 {
19 type Value = T;
20
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result21 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
22 formatter.write_str("an integer or string")
23 }
24
visit_u64<E>(self, v: u64) -> Result<Self::Value, E> where E: serde::de::Error,25 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
26 where
27 E: serde::de::Error,
28 {
29 T::try_from(v).map_err(serde::de::Error::custom)
30 }
31
visit_i64<E>(self, v: i64) -> Result<Self::Value, E> where E: serde::de::Error,32 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
33 where
34 E: serde::de::Error,
35 {
36 T::try_from(v).map_err(serde::de::Error::custom)
37 }
38
visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error,39 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
40 where
41 E: serde::de::Error,
42 {
43 v.parse().map_err(serde::de::Error::custom)
44 }
45 }
46
deserialize_integer_or_string<'de, D, T>(deserializer: D) -> Result<T, D::Error> where D: Deserializer<'de>, T: TryFrom<u64> + TryFrom<i64> + FromStr, <T as TryFrom<u64>>::Error: Display, <T as TryFrom<i64>>::Error: Display, <T as FromStr>::Err: Display,47 fn deserialize_integer_or_string<'de, D, T>(deserializer: D) -> Result<T, D::Error>
48 where
49 D: Deserializer<'de>,
50 T: TryFrom<u64> + TryFrom<i64> + FromStr,
51 <T as TryFrom<u64>>::Error: Display,
52 <T as TryFrom<i64>>::Error: Display,
53 <T as FromStr>::Err: Display,
54 {
55 deserializer.deserialize_any(NumberVisitor {
56 marker: PhantomData,
57 })
58 }
59
60 #[derive(Deserialize, Debug)]
61 pub struct Struct {
62 #[serde(deserialize_with = "deserialize_integer_or_string")]
63 #[allow(dead_code)]
64 pub i: i64,
65 }
66
67 #[test]
test()68 fn test() {
69 let j = r#" {"i":100} "#;
70 println!("{:?}", serde_json::from_str::<Struct>(j).unwrap());
71
72 let j = r#" {"i":"100"} "#;
73 println!("{:?}", serde_json::from_str::<Struct>(j).unwrap());
74 }
75