• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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