use core::{convert::TryFrom as _, fmt};
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use crate::Month;
pub mod serde_str {
use serde::{Deserializer, Serializer};
use super::{Month, MonthVisitor};
pub fn serialize<S>(month: &Month, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(month.to_string().as_str())
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Month, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(MonthVisitor)
}
}
pub mod serde_u64 {
use serde::{Deserializer, Serializer};
use super::{Month, MonthVisitor};
pub fn serialize<S>(month: &Month, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_u64(month.to_owned() as u64)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Month, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_u64(MonthVisitor)
}
}
impl Serialize for Month {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_str())
}
}
impl<'de> Deserialize<'de> for Month {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(MonthVisitor)
}
}
struct MonthVisitor;
impl<'de> Visitor<'de> for MonthVisitor {
type Value = Month;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("str or u8")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
v.parse::<Self::Value>().map_err(de::Error::custom)
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
Self::Value::try_from(v as u8).map_err(de::Error::custom)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
Self::Value::try_from(v as u8).map_err(de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[derive(Deserialize, Serialize, PartialEq, Debug)]
struct Foo {
#[serde(with = "crate::serde_str")]
m1: Month,
#[serde(with = "crate::serde_u64")]
m2: Month,
#[serde(
serialize_with = "crate::serde_str::serialize",
deserialize_with = "crate::serde_u64::deserialize"
)]
m3: Month,
m4: Month,
}
#[test]
fn de() {
let json = r#"{ "m1": "January", "m2": 2, "m3": 3, "m4": "Apr" }"#;
assert_eq!(
serde_json::from_str::<Foo>(json).unwrap(),
Foo {
m1: Month::Jan,
m2: Month::Feb,
m3: Month::Mar,
m4: Month::Apr,
}
);
let json = r#"{ "m1": "January", "m2": 2, "m3": 3, "m4": 4 }"#;
assert_eq!(
serde_json::from_str::<Foo>(json).unwrap(),
Foo {
m1: Month::Jan,
m2: Month::Feb,
m3: Month::Mar,
m4: Month::Apr,
}
);
}
#[test]
fn ser() {
assert_eq!(
serde_json::to_value(&Foo {
m1: Month::Jan,
m2: Month::Feb,
m3: Month::Mar,
m4: Month::Apr,
})
.unwrap(),
json!({
"m1": "Jan", "m2": 2, "m3": "Mar", "m4": "Apr"
})
);
}
}