serde_flexible/deserialize/
as_string_opt.rs1use serde::de::{Deserializer, Error, Visitor};
2use std::fmt;
3
4const EXPECTED: &str = "null, a string, bool, or a number";
5
6pub fn as_string_opt<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<String>, D::Error> {
7 deserializer.deserialize_any(AsOptString)
8}
9
10struct AsOptString;
11
12impl<'de> Visitor<'de> for AsOptString {
13 type Value = Option<String>;
14
15 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
16 formatter.write_str(EXPECTED)
17 }
18
19 fn visit_bool<E: Error>(self, v: bool) -> Result<Self::Value, E> {
20 Ok(Some(v.to_string()))
21 }
22 fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
23 Ok(Some(v.to_string()))
24 }
25 fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
26 Ok(Some(v.to_string()))
27 }
28 fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
29 Ok(Some(v.to_string()))
30 }
31 fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
32 Ok(Some(v.to_owned()))
33 }
34 fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
35 Ok(None)
36 }
37}
38
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use serde::Deserialize;
44
45 #[derive(Debug, Deserialize, PartialEq)]
46 struct Test {
47 #[serde(deserialize_with = "as_string_opt")]
48 str: Option<String>,
49 }
50
51 #[test]
52 fn test_base_good_parse() {
53 assert_eq!(serde_json::from_str::<Test>(r#"{"str": "null" }"#).unwrap().str.unwrap(), "null");
55 assert_eq!(serde_json::from_str::<Test>(r#"{"str": "none" }"#).unwrap().str.unwrap(), "none");
56 assert_eq!(serde_json::from_str::<Test>(r#"{"str": "unknown" }"#).unwrap().str.unwrap(), "unknown");
57 assert_eq!(serde_json::from_str::<Test>(r#"{"str": "Unknown" }"#).unwrap().str.unwrap(), "Unknown");
58 assert_eq!(serde_json::from_str::<Test>(r#"{"str": "NONE" }"#).unwrap().str.unwrap(), "NONE");
59 assert!(serde_json::from_str::<Test>(r#"{"str": null }"#).unwrap().str.is_none());
60
61 assert_eq!(serde_json::from_str::<Test>(r#"{"str": "Foo Boo" }"#).unwrap().str.unwrap(), "Foo Boo");
62 assert_eq!(serde_json::from_str::<Test>(r#"{"str": "hello" }"#).unwrap().str.unwrap(), "hello");
63 assert_eq!(serde_json::from_str::<Test>(r#"{"str": 100 }"#).unwrap().str.unwrap(), "100");
64 assert_eq!(serde_json::from_str::<Test>(r#"{"str": true }"#).unwrap().str.unwrap(), "true");
65 assert_eq!(serde_json::from_str::<Test>(r#"{"str": false }"#).unwrap().str.unwrap(), "false");
66 assert_eq!(serde_json::from_str::<Test>(r#"{"str": 12345 }"#).unwrap().str.unwrap(), "12345");
67 assert_eq!(serde_json::from_str::<Test>(r#"{"str": -12345 }"#).unwrap().str.unwrap(), "-12345");
68 assert_eq!(serde_json::from_str::<Test>(r#"{"str": -0 }"#).unwrap().str.unwrap(), "-0");
69 assert_eq!(serde_json::from_str::<Test>(r#"{"str": 0 }"#).unwrap().str.unwrap(), "0");
70 assert_eq!(serde_json::from_str::<Test>(r#"{"str": 3.14 }"#).unwrap().str.unwrap(), "3.14");
71
72 assert!(serde_json::from_str::<Test>(r#"{"str": null }"#).unwrap().str.is_none());
73 }
74
75 #[test]
76 fn test_base_error() {
77 assert!(serde_json::from_str::<Test>(r#"{"str": ["hello"]] }"#).is_err());
78 }
79}