Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use void::Void;
- extern crate serde;
- use serde::{Deserialize, Serialize};
- use serde::de::Deserializer;
- use std::marker::PhantomData;
- use std::str::FromStr;
- use std::fmt;
- use serde::de::Visitor;
- use serde::de;
- #[derive(Serialize, Deserialize)]
- struct Wow {
- #[serde(deserialize_with = "bool_or_string")]
- hello: String,
- }
- fn bool_or_string<'de, T, D>(deserializer: D) -> Result<T, D::Error>
- where
- T: Deserialize<'de> + FromStr<Err = Void>,
- D: Deserializer<'de>,
- {
- // This is a Visitor that forwards string types to T's `FromStr` impl and
- // forwards map types to T's `Deserialize` impl. The `PhantomData` is to
- // keep the compiler from complaining about T being an unused generic type
- // parameter. We need T in order to know the Value type for the Visitor
- // impl.
- struct BoolOrString<T>(PhantomData<fn() -> T>);
- impl<'de, T> Visitor<'de> for BoolOrString<T>
- where
- T: Deserialize<'de> + FromStr<Err = Void>,
- {
- type Value = T;
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("bool or string")
- }
- fn visit_bool<E>(self, value: &str) -> Result<&str, E>
- where
- E: de::Error,
- {
- Ok(if value {"true"} else {"false"})
- }
- fn visit_str<E>(self, value: &str) -> Result<T, E>
- where
- E: de::Error,
- {
- Ok(FromStr::from_str(value).unwrap())
- }
- }
- deserializer.deserialize_any(BoolOrString(PhantomData))
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- #[test]
- fn test_parsing() {
- let data0 = r#"{
- "hello": "yeah"
- ]
- }"#;
- let data1 = r#"{
- "hello": false
- ]
- }"#;
- let wow0: Wow = serde_json::from_str(data0).unwrap();
- let wow1: Wow = serde_json::from_str(data1).unwrap();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement