Skip to main content

asknothingx2_util/serde/
mod.rs

1use std::fmt::Display;
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer, de::IntoDeserializer};
4
5/// <https://github.com/serde-rs/serde/issues/2362>
6pub fn deserialize_empty_object_as_none<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
7where
8    D: Deserializer<'de>,
9    T: Deserialize<'de>,
10{
11    #[derive(Deserialize)]
12    #[serde(
13        untagged,
14        deny_unknown_fields,
15        expecting = "object, empty object or null"
16    )]
17    enum Helper<T> {
18        Data(T),
19        Empty {},
20        Null,
21    }
22    match Helper::deserialize(deserializer) {
23        Ok(Helper::Data(data)) => Ok(Some(data)),
24        Ok(_) => Ok(None),
25        Err(e) => Err(e),
26    }
27}
28
29pub fn deserialize_empty_string_as_none<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
30where
31    D: Deserializer<'de>,
32    T: Deserialize<'de>,
33{
34    let opt = Option::<String>::deserialize(deserializer)?;
35    match opt {
36        Some(s) if s.is_empty() => Ok(None),
37        Some(s) => T::deserialize(s.into_deserializer()).map(Some),
38        None => Ok(None),
39    }
40}
41
42pub fn serialize_none_as_empty_string<T, S>(
43    value: &Option<T>,
44    serializer: S,
45) -> Result<S::Ok, S::Error>
46where
47    S: Serializer,
48    T: Serialize,
49{
50    match value {
51        None => serializer.serialize_str(""),
52        Some(v) => v.serialize(serializer),
53    }
54}
55
56pub fn serialize_none_as_empty_object<S, T>(
57    value: &Option<T>,
58    serializer: S,
59) -> Result<S::Ok, S::Error>
60where
61    S: Serializer,
62    T: Serialize,
63{
64    match value {
65        Some(v) => v.serialize(serializer),
66        None => {
67            use serde::ser::SerializeMap;
68            let map = serializer.serialize_map(Some(0))?;
69            map.end()
70        }
71    }
72}
73
74pub fn deserialize_empty_array_as_none<'de, D, T>(
75    deserializer: D,
76) -> Result<Option<Vec<T>>, D::Error>
77where
78    D: Deserializer<'de>,
79    T: Deserialize<'de>,
80{
81    let vec: Vec<T> = Vec::deserialize(deserializer)?;
82    Ok(if vec.is_empty() { None } else { Some(vec) })
83}
84
85pub fn serialize_none_as_empty_array<S, T>(
86    value: &Option<Vec<T>>,
87    serializer: S,
88) -> Result<S::Ok, S::Error>
89where
90    S: Serializer,
91    T: Serialize,
92{
93    match value {
94        Some(v) => v.serialize(serializer),
95        None => {
96            use serde::ser::SerializeSeq;
97            let seq = serializer.serialize_seq(Some(0))?;
98            seq.end()
99        }
100    }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
104pub struct EmptyObject;
105
106impl Display for EmptyObject {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        f.write_str("{}")
109    }
110}
111
112impl Serialize for EmptyObject {
113    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
114    where
115        S: Serializer,
116    {
117        use serde::ser::SerializeMap;
118        let map = serializer.serialize_map(Some(0))?;
119        map.end()
120    }
121}
122
123impl<'de> Deserialize<'de> for EmptyObject {
124    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
125    where
126        D: Deserializer<'de>,
127    {
128        use serde::de::{Error, Visitor};
129
130        struct EmptyObjectVisitor;
131        impl<'de> Visitor<'de> for EmptyObjectVisitor {
132            type Value = EmptyObject;
133            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
134                formatter.write_str(stringify!(EmptyObject))
135            }
136
137            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
138            where
139                A: serde::de::MapAccess<'de>,
140            {
141                if let Some(key) = map.next_key::<String>()? {
142                    return Err(Error::custom(format!(
143                        "expected empty object, but found field: {}",
144                        key
145                    )));
146                }
147                Ok(EmptyObject)
148            }
149        }
150
151        deserializer.deserialize_map(EmptyObjectVisitor)
152    }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub struct EmptyArray;
157
158impl Display for EmptyArray {
159    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160        f.write_str("[]")
161    }
162}
163
164impl Serialize for EmptyArray {
165    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
166    where
167        S: Serializer,
168    {
169        use serde::ser::SerializeSeq;
170        let seq = serializer.serialize_seq(Some(0))?;
171        seq.end()
172    }
173}
174
175impl<'de> Deserialize<'de> for EmptyArray {
176    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
177    where
178        D: Deserializer<'de>,
179    {
180        use serde::de::{Error, Visitor};
181        struct EmptyArrayVisitor;
182        impl<'de> Visitor<'de> for EmptyArrayVisitor {
183            type Value = EmptyArray;
184            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
185                formatter.write_str(stringify!(EmptyArray))
186            }
187
188            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
189            where
190                A: serde::de::SeqAccess<'de>,
191            {
192                if let Some(_element) = seq.next_element::<serde_json::Value>()? {
193                    return Err(Error::custom("expected empty array, but found element"));
194                }
195                Ok(EmptyArray)
196            }
197        }
198        deserializer.deserialize_seq(EmptyArrayVisitor)
199    }
200}
201
202#[cfg(test)]
203mod tests {
204    use serde::{Deserialize, Serialize};
205
206    use crate::serde::{
207        deserialize_empty_array_as_none, deserialize_empty_object_as_none,
208        deserialize_empty_string_as_none, serialize_none_as_empty_array,
209        serialize_none_as_empty_object, serialize_none_as_empty_string,
210    };
211
212    #[derive(Debug, PartialEq, Deserialize, Serialize)]
213    struct Struct {
214        name: String,
215        value: i32,
216    }
217
218    #[derive(Debug, PartialEq, Deserialize, Serialize)]
219    struct EmptyObject {
220        #[serde(deserialize_with = "deserialize_empty_object_as_none")]
221        #[serde(serialize_with = "serialize_none_as_empty_object")]
222        data: Option<Struct>,
223    }
224
225    #[derive(Debug, PartialEq, Deserialize, Serialize)]
226    struct EmptyString {
227        #[serde(deserialize_with = "deserialize_empty_string_as_none")]
228        #[serde(serialize_with = "serialize_none_as_empty_string")]
229        value: Option<String>,
230    }
231
232    #[derive(Debug, PartialEq, Deserialize, Serialize)]
233    struct EmptyArray {
234        #[serde(deserialize_with = "deserialize_empty_array_as_none")]
235        #[serde(serialize_with = "serialize_none_as_empty_array")]
236        items: Option<Vec<String>>,
237    }
238
239    mod empty_object {
240        use crate::serde::tests::{EmptyObject, Struct};
241
242        #[test]
243        fn deserialize_empty_object_as_none() {
244            let json = r#"{"data": {}}"#;
245            let result: EmptyObject = serde_json::from_str(json).unwrap();
246            assert_eq!(result.data, None);
247        }
248
249        #[test]
250        fn deserialize_null_as_none() {
251            let json = r#"{"data": null}"#;
252            let result: EmptyObject = serde_json::from_str(json).unwrap();
253            assert_eq!(result.data, None);
254        }
255
256        #[test]
257        fn deserialize_valid_object() {
258            let json = r#"{"data": {"name": "test", "value": 62}}"#;
259            let result: EmptyObject = serde_json::from_str(json).unwrap();
260            assert_eq!(
261                result.data,
262                Some(Struct {
263                    name: "test".to_string(),
264                    value: 62
265                })
266            );
267        }
268
269        #[test]
270        fn deserialize_invalid_object_fails() {
271            let json = r#"{"data": {"unknown_field": "value"}}"#;
272            let result: Result<EmptyObject, _> = serde_json::from_str(json);
273            assert!(result.is_err());
274        }
275
276        #[test]
277        fn serialize_none_as_empty_object() {
278            let test_data = EmptyObject { data: None };
279            let json = serde_json::to_string(&test_data).unwrap();
280            assert_eq!(json, r#"{"data":{}}"#);
281        }
282
283        #[test]
284        fn serialize_some_as_object() {
285            let test_data = EmptyObject {
286                data: Some(Struct {
287                    name: "test".to_string(),
288                    value: 62,
289                }),
290            };
291            let json = serde_json::to_string(&test_data).unwrap();
292            assert_eq!(json, r#"{"data":{"name":"test","value":62}}"#);
293        }
294
295        #[test]
296        fn roundtrip_none() {
297            let original = EmptyObject { data: None };
298            let json = serde_json::to_string(&original).unwrap();
299            let deserialized: EmptyObject = serde_json::from_str(&json).unwrap();
300            assert_eq!(original, deserialized);
301        }
302
303        #[test]
304        fn roundtrip_some() {
305            let original = EmptyObject {
306                data: Some(Struct {
307                    name: "test".to_string(),
308                    value: 62,
309                }),
310            };
311            let json = serde_json::to_string(&original).unwrap();
312            let deserialized: EmptyObject = serde_json::from_str(&json).unwrap();
313            assert_eq!(original, deserialized);
314        }
315    }
316
317    mod empty_string {
318        use crate::serde::tests::EmptyString;
319
320        #[test]
321        fn deserialize_empty_string_as_none() {
322            let json = r#"{"value": ""}"#;
323            let result: EmptyString = serde_json::from_str(json).unwrap();
324            assert_eq!(result.value, None);
325        }
326
327        #[test]
328        fn deserialize_null_string_as_none() {
329            let json = r#"{"value": null}"#;
330            let result: EmptyString = serde_json::from_str(json).unwrap();
331            assert_eq!(result.value, None);
332        }
333
334        #[test]
335        fn deserialize_valid_string() {
336            let json = r#"{"value": "hello"}"#;
337            let result: EmptyString = serde_json::from_str(json).unwrap();
338            assert_eq!(result.value, Some("hello".to_string()));
339        }
340
341        #[test]
342        fn deserialize_whitespace_string() {
343            let json = r#"{"value": " "}"#;
344            let result: EmptyString = serde_json::from_str(json).unwrap();
345            assert_eq!(result.value, Some(" ".to_string()));
346        }
347
348        #[test]
349        fn serialize_none_as_empty_string() {
350            let test_data = EmptyString { value: None };
351            let json = serde_json::to_string(&test_data).unwrap();
352            assert_eq!(json, r#"{"value":""}"#);
353        }
354
355        #[test]
356        fn serialize_some_as_string() {
357            let test_data = EmptyString {
358                value: Some("hello".to_string()),
359            };
360            let json = serde_json::to_string(&test_data).unwrap();
361            assert_eq!(json, r#"{"value":"hello"}"#);
362        }
363
364        #[test]
365        fn roundtrip_none() {
366            let original = EmptyString { value: None };
367            let json = serde_json::to_string(&original).unwrap();
368            let deserialized: EmptyString = serde_json::from_str(&json).unwrap();
369            assert_eq!(original, deserialized);
370        }
371
372        #[test]
373        fn roundtrip_some() {
374            let original = EmptyString {
375                value: Some("test".to_string()),
376            };
377            let json = serde_json::to_string(&original).unwrap();
378            let deserialized: EmptyString = serde_json::from_str(&json).unwrap();
379            assert_eq!(original, deserialized);
380        }
381    }
382
383    mod empty_array {
384        use crate::serde::tests::EmptyArray;
385
386        #[test]
387        fn deserialize_empty_array_as_none() {
388            let json = r#"{"items": []}"#;
389            let result: EmptyArray = serde_json::from_str(json).unwrap();
390            assert_eq!(result.items, None);
391        }
392
393        #[test]
394        fn deserialize_valid_array() {
395            let json = r#"{"items": ["a", "b", "c"]}"#;
396            let result: EmptyArray = serde_json::from_str(json).unwrap();
397            assert_eq!(
398                result.items,
399                Some(vec!["a".to_string(), "b".to_string(), "c".to_string()])
400            );
401        }
402
403        #[test]
404        fn deserialize_single_item_array() {
405            let json = r#"{"items": ["single"]}"#;
406            let result: EmptyArray = serde_json::from_str(json).unwrap();
407            assert_eq!(result.items, Some(vec!["single".to_string()]));
408        }
409
410        #[test]
411        fn serialize_none_as_empty_array() {
412            let test_data = EmptyArray { items: None };
413            let json = serde_json::to_string(&test_data).unwrap();
414            assert_eq!(json, r#"{"items":[]}"#);
415        }
416
417        #[test]
418        fn serialize_some_as_array() {
419            let test_data = EmptyArray {
420                items: Some(vec!["a".to_string(), "b".to_string()]),
421            };
422            let json = serde_json::to_string(&test_data).unwrap();
423            assert_eq!(json, r#"{"items":["a","b"]}"#);
424        }
425
426        #[test]
427        fn serialize_empty_vec_as_array() {
428            let test_data = EmptyArray {
429                items: Some(Vec::new()),
430            };
431            let json = serde_json::to_string(&test_data).unwrap();
432            assert_eq!(json, r#"{"items":[]}"#);
433        }
434
435        #[test]
436        fn roundtrip_none() {
437            let original = EmptyArray { items: None };
438            let json = serde_json::to_string(&original).unwrap();
439            let deserialized: EmptyArray = serde_json::from_str(&json).unwrap();
440            assert_eq!(original, deserialized);
441        }
442
443        #[test]
444        fn roundtrip_some() {
445            let original = EmptyArray {
446                items: Some(vec!["test".to_string(), "data".to_string()]),
447            };
448            let json = serde_json::to_string(&original).unwrap();
449            let deserialized: EmptyArray = serde_json::from_str(&json).unwrap();
450            assert_eq!(original, deserialized);
451        }
452    }
453
454    mod strict_empty {
455        use crate::serde::{EmptyArray, EmptyObject};
456
457        #[test]
458        fn array() {
459            let empty = EmptyArray;
460            let json = serde_json::to_string(&empty).unwrap();
461            assert_eq!(json, "[]");
462
463            let deserialized: EmptyArray = serde_json::from_str(&json).unwrap();
464            assert_eq!(empty, deserialized);
465
466            assert_eq!("[]", EmptyArray.to_string());
467        }
468
469        #[test]
470        fn object() {
471            let object = EmptyObject;
472            let json = serde_json::to_string(&object).unwrap();
473            assert_eq!(json, "{}");
474
475            let deserialized: EmptyObject = serde_json::from_str(&json).unwrap();
476            assert_eq!(object, deserialized);
477
478            assert_eq!("{}", EmptyObject.to_string());
479        }
480    }
481}