From 7eb2143b2c238e8c426e6af04d7fac1ed3aa2d9f Mon Sep 17 00:00:00 2001 From: Sunli Date: Mon, 21 Sep 2020 15:22:45 +0800 Subject: [PATCH] Implement Serialize/Deserialize for MaybeUndefine. --- src/types/maybe_undefined.rs | 105 +++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/src/types/maybe_undefined.rs b/src/types/maybe_undefined.rs index 68c2ad18..d3175633 100644 --- a/src/types/maybe_undefined.rs +++ b/src/types/maybe_undefined.rs @@ -1,5 +1,5 @@ use crate::{registry, InputValueResult, InputValueType, Type, Value}; -use serde::Serialize; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; /// Similar to `Option`, but it has three states, `undefined`, `null` and `x`. @@ -46,14 +46,19 @@ use std::borrow::Cow; /// } /// ``` #[allow(missing_docs)] -#[derive(Serialize, Clone, Debug)] -#[serde(untagged)] +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] pub enum MaybeUndefined { Undefined, Null, Value(T), } +impl Default for MaybeUndefined { + fn default() -> Self { + Self::Undefined + } +} + impl MaybeUndefined { /// Returns true if the MaybeUndefined is undefined. #[inline] @@ -136,15 +141,107 @@ impl InputValueType for MaybeUndefined { } } +impl Serialize for MaybeUndefined { + fn serialize(&self, serializer: S) -> std::result::Result { + match self { + MaybeUndefined::Value(value) => value.serialize(serializer), + _ => serializer.serialize_none(), + } + } +} + +impl<'de, T> Deserialize<'de> for MaybeUndefined +where + T: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + Option::::deserialize(deserializer).map(|value| match value { + Some(value) => MaybeUndefined::Value(value), + None => MaybeUndefined::Null, + }) + } +} + #[cfg(test)] mod tests { use crate::*; + use serde::{Deserialize, Serialize}; #[test] - fn test_optional_type() { + fn test_maybe_undefined_type() { assert_eq!(MaybeUndefined::::type_name(), "Int"); assert_eq!(MaybeUndefined::::qualified_type_name(), "Int"); assert_eq!(&MaybeUndefined::::type_name(), "Int"); assert_eq!(&MaybeUndefined::::qualified_type_name(), "Int"); } + + #[test] + fn test_maybe_undefined_serde() { + assert_eq!( + serde_json::to_string(&MaybeUndefined::Value(100i32)).unwrap(), + "100" + ); + + assert_eq!( + serde_json::from_str::>("100").unwrap(), + MaybeUndefined::Value(100) + ); + assert_eq!( + serde_json::from_str::>("null").unwrap(), + MaybeUndefined::Null + ); + + #[derive(Serialize, Deserialize, Eq, PartialEq, Debug)] + struct A { + a: MaybeUndefined, + } + + assert_eq!( + serde_json::to_string(&A { + a: MaybeUndefined::Value(100i32) + }) + .unwrap(), + r#"{"a":100}"# + ); + + assert_eq!( + serde_json::to_string(&A { + a: MaybeUndefined::Null, + }) + .unwrap(), + r#"{"a":null}"# + ); + + assert_eq!( + serde_json::to_string(&A { + a: MaybeUndefined::Undefined, + }) + .unwrap(), + r#"{"a":null}"# + ); + + assert_eq!( + serde_json::from_str::(r#"{"a":100}"#).unwrap(), + A { + a: MaybeUndefined::Value(100i32) + } + ); + + assert_eq!( + serde_json::from_str::(r#"{"a":null}"#).unwrap(), + A { + a: MaybeUndefined::Null + } + ); + + assert_eq!( + serde_json::from_str::(r#"{}"#).unwrap(), + A { + a: MaybeUndefined::Null + } + ); + } }