• 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::convert::TryFrom;
5 use std::fmt::{self, Display};
6 use std::marker::PhantomData;
7 use std::str::FromStr;
8 
9 pub struct NumberVisitor<T> {
10     marker: PhantomData<T>,
11 }
12 
13 impl<'de, T> serde::de::Visitor<'de> for NumberVisitor<T>
14 where
15     T: TryFrom<u64> + TryFrom<i64> + FromStr,
16     <T as TryFrom<u64>>::Error: Display,
17     <T as TryFrom<i64>>::Error: Display,
18     <T as FromStr>::Err: Display,
19 {
20     type Value = T;
21 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result22     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
23         formatter.write_str("an integer or string")
24     }
25 
visit_u64<E>(self, v: u64) -> Result<Self::Value, E> where E: serde::de::Error,26     fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
27     where
28         E: serde::de::Error,
29     {
30         T::try_from(v).map_err(serde::de::Error::custom)
31     }
32 
visit_i64<E>(self, v: i64) -> Result<Self::Value, E> where E: serde::de::Error,33     fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
34     where
35         E: serde::de::Error,
36     {
37         T::try_from(v).map_err(serde::de::Error::custom)
38     }
39 
visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error,40     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
41     where
42         E: serde::de::Error,
43     {
44         v.parse().map_err(serde::de::Error::custom)
45     }
46 }
47 
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,48 fn deserialize_integer_or_string<'de, D, T>(deserializer: D) -> Result<T, D::Error>
49 where
50     D: Deserializer<'de>,
51     T: TryFrom<u64> + TryFrom<i64> + FromStr,
52     <T as TryFrom<u64>>::Error: Display,
53     <T as TryFrom<i64>>::Error: Display,
54     <T as FromStr>::Err: Display,
55 {
56     deserializer.deserialize_any(NumberVisitor {
57         marker: PhantomData,
58     })
59 }
60 
61 #[derive(Deserialize, Debug)]
62 pub struct Struct {
63     #[serde(deserialize_with = "deserialize_integer_or_string")]
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