use std::fmt::Display;
use std::str::FromStr;
use std::{borrow::Cow, fmt};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
#[allow(dead_code)]
fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
T: FromStr,
T::Err: fmt::Display,
{
let opt = Option::<String>::deserialize(de)?;
match opt.as_deref() {
None | Some("") => Ok(None),
Some(s) => FromStr::from_str(s).map_err(de::Error::custom).map(Some),
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct StupidValue<T>(pub T);
impl<T> Serialize for StupidValue<T>
where
T: ToString,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_string().serialize(serializer)
}
}
impl<'de, T> Deserialize<'de> for StupidValue<T>
where
T: FromStr + Deserialize<'de>,
T::Err: Display,
{
fn deserialize<D>(deserializer: D) -> Result<StupidValue<T>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum StrOrValue<'a, T> {
Str(Cow<'a, str>),
Value(T),
}
let str_or_val = StrOrValue::<T>::deserialize(deserializer)?;
Ok(StupidValue(match str_or_val {
StrOrValue::Value(val) => val,
StrOrValue::Str(s) => s.parse().map_err(serde::de::Error::custom)?,
}))
}
}
impl<T> From<T> for StupidValue<T> {
fn from(val: T) -> Self {
StupidValue(val)
}
}
pub mod my_date_format {
use chrono::NaiveDateTime;
use serde::{self, Deserialize, Deserializer, Serializer};
const FORMAT: &str = "%Y-%m-%d %H:%M:%S";
pub fn serialize<S>(date: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = format!("{}", date.format(FORMAT));
serializer.serialize_str(&s)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<NaiveDateTime, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?;
Ok(dt)
}
}
pub mod my_date_format_option {
use super::my_date_format;
use chrono::NaiveDateTime;
use serde::{self, Deserialize, Deserializer, Serializer};
const FORMAT: &str = "%Y-%m-%d %H:%M:%S";
pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *opt {
Some(ref dt) => my_date_format::serialize(dt, serializer),
None => serializer.serialize_none(),
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDateTime>, D::Error>
where
D: Deserializer<'de>,
{
match Option::<String>::deserialize(deserializer)? {
Some(s) => {
let dt = NaiveDateTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom)?;
Ok(Some(dt))
}
None => Ok(None),
}
}
}