serde_decimal/
non_required_float.rs1use std::fmt;
4
5use rust_decimal::Decimal;
6use serde_core::{de, Deserialize, Deserializer, Serializer};
7
8struct OptionDecimalVisitor;
9
10impl<'de> de::Visitor<'de> for OptionDecimalVisitor {
11 type Value = Option<Decimal>;
12
13 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
14 formatter.write_str("a Decimal type representing a fixed-point number")
15 }
16
17 fn visit_some<D>(self, d: D) -> Result<Option<Decimal>, D::Error>
18 where
19 D: Deserializer<'de>,
20 {
21 <Decimal as Deserialize>::deserialize(d).map(Some)
22 }
23}
24
25pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<rust_decimal::Decimal>, D::Error>
29where
30 D: Deserializer<'de>,
31{
32 deserializer.deserialize_option(OptionDecimalVisitor)
33}
34
35pub fn serialize<S>(value: &Option<rust_decimal::Decimal>, serializer: S) -> Result<S::Ok, S::Error>
39where
40 S: Serializer,
41{
42 rust_decimal::serde::float_option::serialize(value, serializer)
43}
44
45#[cfg(test)]
46mod tests {
47 use rust_decimal_macros::dec;
48
49 #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
50 struct Foo {
51 #[serde(default)]
52 #[serde(skip_serializing_if = "Option::is_none")]
53 #[serde(with = "crate::non_required_float")]
54 foo: Option<rust_decimal::Decimal>,
55 }
56
57 #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
58 struct Bar {
59 #[serde(flatten)]
60 foo: Foo,
61 }
62
63 #[test]
64 fn foo_serialize_some() {
65 let serialized = serde_json::to_string(&Foo {
66 foo: Some(dec!(0.1)),
67 })
68 .unwrap();
69 assert_eq!(serialized, r#"{"foo":0.1}"#);
70 }
71
72 #[test]
73 fn foo_serialize_none() {
74 let serialized = serde_json::to_string(&Foo { foo: None }).unwrap();
75 assert_eq!(serialized, r#"{}"#);
76 }
77
78 #[test]
79 fn foo_deserialize_some() {
80 let deserialized: Foo = serde_json::from_str(r#"{"foo":0.1}"#).unwrap();
81 assert!(matches!(deserialized, Foo { foo: Some(_) }));
82 }
83
84 #[test]
85 fn foo_deserialize_missing() {
86 let deserialized: Foo = serde_json::from_str(r#"{}"#).unwrap();
87 assert!(matches!(deserialized, Foo { foo: None }));
88 }
89
90 #[test]
91 #[should_panic]
92 fn foo_deserialize_null() {
93 serde_json::from_str::<Foo>(r#"{"foo": null}"#).unwrap();
94 }
95
96 #[test]
97 fn bar_serialize_some() {
98 let serialized = serde_json::to_string(&Bar {
99 foo: Foo {
100 foo: Some(dec!(0.1)),
101 },
102 })
103 .unwrap();
104 assert_eq!(serialized, r#"{"foo":0.1}"#);
105 }
106
107 #[test]
108 fn bar_serialize_none() {
109 let serialized = serde_json::to_string(&Bar {
110 foo: Foo { foo: None },
111 })
112 .unwrap();
113 assert_eq!(serialized, r#"{}"#);
114 }
115
116 #[test]
117 fn bar_deserialize_some() {
118 let deserialized: Bar = serde_json::from_str(r#"{"foo":0.1}"#).unwrap();
119 assert!(matches!(
120 deserialized,
121 Bar {
122 foo: Foo { foo: Some(_) }
123 }
124 ));
125 }
126
127 #[test]
128 fn bar_deserialize_missing() {
129 let deserialized: Bar = serde_json::from_str(r#"{}"#).unwrap();
130 assert!(matches!(
131 deserialized,
132 Bar {
133 foo: Foo { foo: None }
134 }
135 ));
136 }
137
138 #[test]
139 #[should_panic]
140 fn bar_deserialize_null() {
141 serde_json::from_str::<Bar>(r#"{"foo": null}"#).unwrap();
142 }
143}