nomad_api_types/
utils.rs

1use serde::{Deserialize, Deserializer};
2
3pub fn deserialize_null_as_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
4where
5    T: Default + Deserialize<'de>,
6    D: Deserializer<'de>,
7{
8    Option::deserialize(deserializer).map(Option::unwrap_or_default)
9}
10
11#[cfg(test)]
12mod tests {
13    use std::collections::HashMap;
14
15    use serde::Deserialize;
16
17    #[derive(Debug, Deserialize, PartialEq, Eq)]
18    struct TestData {
19        #[serde(deserialize_with = "crate::deserialize_null_as_default")]
20        pub string: String,
21
22        #[serde(deserialize_with = "crate::deserialize_null_as_default")]
23        pub number: i64,
24
25        #[serde(deserialize_with = "crate::deserialize_null_as_default")]
26        pub boolean: bool,
27
28        #[serde(deserialize_with = "crate::deserialize_null_as_default")]
29        pub list: Vec<String>,
30
31        #[serde(deserialize_with = "crate::deserialize_null_as_default")]
32        pub map: std::collections::HashMap<String, i64>,
33    }
34
35    #[test]
36    pub fn deserialize_null_as_default_deserializes_value() {
37        let input = r#"{"string":"data","number":42,"boolean":true,"list":["a","b","c"],"map":{"a":1,"b":2,"c":3}}"#;
38
39        let value = serde_json::from_str::<TestData>(input).unwrap();
40
41        assert_eq!(
42            value,
43            TestData {
44                string: "data".into(),
45                number: 42,
46                boolean: true,
47                list: vec!["a".into(), "b".into(), "c".into()],
48                map: HashMap::from([("a".into(), 1), ("b".into(), 2), ("c".into(), 3)])
49            }
50        )
51    }
52
53    #[test]
54    pub fn deserialize_null_as_default_deserializes_null_as_default() {
55        let input = r#"{"string":null,"number":null,"boolean":null,"list":null,"map":null}"#;
56
57        let value = serde_json::from_str::<TestData>(input).unwrap();
58
59        assert_eq!(
60            value,
61            TestData {
62                string: "".into(),
63                number: 0,
64                boolean: false,
65                list: vec![],
66                map: HashMap::new()
67            }
68        )
69    }
70}