Implement Serialize/Deserialize for MaybeUndefine<T>.
This commit is contained in:
parent
e12ae8b236
commit
7eb2143b2c
|
@ -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<T> {
|
||||
Undefined,
|
||||
Null,
|
||||
Value(T),
|
||||
}
|
||||
|
||||
impl<T> Default for MaybeUndefined<T> {
|
||||
fn default() -> Self {
|
||||
Self::Undefined
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MaybeUndefined<T> {
|
||||
/// Returns true if the MaybeUndefined<T> is undefined.
|
||||
#[inline]
|
||||
|
@ -136,15 +141,107 @@ impl<T: InputValueType> InputValueType for MaybeUndefined<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Serialize> Serialize for MaybeUndefined<T> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
|
||||
match self {
|
||||
MaybeUndefined::Value(value) => value.serialize(serializer),
|
||||
_ => serializer.serialize_none(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T> Deserialize<'de> for MaybeUndefined<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<MaybeUndefined<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Option::<T>::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::<i32>::type_name(), "Int");
|
||||
assert_eq!(MaybeUndefined::<i32>::qualified_type_name(), "Int");
|
||||
assert_eq!(&MaybeUndefined::<i32>::type_name(), "Int");
|
||||
assert_eq!(&MaybeUndefined::<i32>::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::<MaybeUndefined<i32>>("100").unwrap(),
|
||||
MaybeUndefined::Value(100)
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<MaybeUndefined<i32>>("null").unwrap(),
|
||||
MaybeUndefined::Null
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
|
||||
struct A {
|
||||
a: MaybeUndefined<i32>,
|
||||
}
|
||||
|
||||
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::<A>(r#"{"a":100}"#).unwrap(),
|
||||
A {
|
||||
a: MaybeUndefined::Value(100i32)
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
serde_json::from_str::<A>(r#"{"a":null}"#).unwrap(),
|
||||
A {
|
||||
a: MaybeUndefined::Null
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
serde_json::from_str::<A>(r#"{}"#).unwrap(),
|
||||
A {
|
||||
a: MaybeUndefined::Null
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user