serde_decimal/
double_option_float.rs

1//! Combination of the serde rules from [rust_decimal::serde::float] and `serde_with::rust::double_option`.
2//!
3//! This is necessary because it is not possible to apply multiple `#[serde(with = ...)]` attributes:
4//! * `#[serde(with = "serde_with::rust::double_option")]`
5//! * `#[serde(with = "rust_decimal::serde::float")]`
6
7/// Double-option float-form decimal deserializer.
8///
9/// See [module docs](self) for more.
10pub fn deserialize<'de, D>(
11    deserializer: D,
12) -> Result<Option<Option<rust_decimal::Decimal>>, D::Error>
13where
14    D: serde::de::Deserializer<'de>,
15{
16    crate::nullable_float::deserialize(deserializer).map(Some)
17}
18
19/// Double-option float-form decimal serializer.
20///
21/// See [module docs](self) for more.
22pub fn serialize<S>(
23    value: &Option<Option<rust_decimal::Decimal>>,
24    serializer: S,
25) -> Result<S::Ok, S::Error>
26where
27    S: serde::Serializer,
28{
29    match value {
30        None => serializer.serialize_unit(),
31        Some(v) => crate::nullable_float::serialize(v, serializer),
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use rust_decimal_macros::dec;
38
39    #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
40    struct Foo {
41        #[serde(skip_serializing_if = "Option::is_none")]
42        #[serde(default)]
43        #[serde(with = "crate::double_option_float")]
44        foo: Option<Option<rust_decimal::Decimal>>,
45    }
46
47    #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
48    struct Bar {
49        #[serde(flatten)]
50        foo: Foo,
51    }
52
53    #[test]
54    fn foo_serialize_some_some() {
55        let serialized = serde_json::to_string(&Foo {
56            foo: Some(Some(dec!(0.1))),
57        })
58        .unwrap();
59        assert_eq!(serialized, r#"{"foo":0.1}"#);
60    }
61
62    #[test]
63    fn foo_serialize_some_none() {
64        let serialized = serde_json::to_string(&Foo { foo: Some(None) }).unwrap();
65        assert_eq!(serialized, r#"{"foo":null}"#);
66    }
67
68    #[test]
69    fn foo_serialize_none() {
70        let serialized = serde_json::to_string(&Foo { foo: None }).unwrap();
71        assert_eq!(serialized, r#"{}"#);
72    }
73
74    #[test]
75    fn foo_deserialize_value() {
76        let deserialized: Foo = serde_json::from_str(r#"{"foo":0.1}"#).unwrap();
77        assert!(matches!(deserialized, Foo { foo: Some(Some(_)) }));
78    }
79
80    #[test]
81    fn foo_deserialize_null() {
82        let deserialized: Foo = serde_json::from_str(r#"{"foo":null}"#).unwrap();
83        assert!(matches!(deserialized, Foo { foo: Some(None) }));
84    }
85
86    #[test]
87    fn foo_deserialize_missing() {
88        let deserialized: Foo = serde_json::from_str(r#"{}"#).unwrap();
89        assert!(matches!(deserialized, Foo { foo: None }));
90    }
91
92    #[test]
93    fn bar_serialize_some_some() {
94        let serialized = serde_json::to_string(&Bar {
95            foo: Foo {
96                foo: Some(Some(dec!(0.1))),
97            },
98        })
99        .unwrap();
100        assert_eq!(serialized, r#"{"foo":0.1}"#);
101    }
102
103    #[test]
104    fn bar_serialize_some_none() {
105        let serialized = serde_json::to_string(&Bar {
106            foo: Foo { foo: Some(None) },
107        })
108        .unwrap();
109        assert_eq!(serialized, r#"{"foo":null}"#);
110    }
111
112    #[test]
113    fn bar_serialize_none() {
114        let serialized = serde_json::to_string(&Bar {
115            foo: Foo { foo: None },
116        })
117        .unwrap();
118        assert_eq!(serialized, r#"{}"#);
119    }
120
121    #[test]
122    fn bar_deserialize_value() {
123        let deserialized: Bar = serde_json::from_str(r#"{"foo":0.1}"#).unwrap();
124        assert!(matches!(
125            deserialized,
126            Bar {
127                foo: Foo { foo: Some(Some(_)) }
128            }
129        ));
130    }
131
132    #[test]
133    fn bar_deserialize_null() {
134        let deserialized: Bar = serde_json::from_str(r#"{"foo":null}"#).unwrap();
135        assert!(matches!(
136            deserialized,
137            Bar {
138                foo: Foo { foo: Some(None) }
139            }
140        ));
141    }
142
143    #[test]
144    fn bar_deserialize_missing() {
145        let deserialized: Bar = serde_json::from_str(r#"{}"#).unwrap();
146        assert!(matches!(
147            deserialized,
148            Bar {
149                foo: Foo { foo: None }
150            }
151        ));
152    }
153}