Hi all, I'm writing some code that interacts with a web API. The timestamps provided by the API are written in a custom format (unix.microseconds
), so I wrote a custom Serializer/Deserializer:
pub mod unix_timestamp {
use chrono::{DateTime, NaiveDateTime, Utc};
use serde::{self, Deserialize, Deserializer, Serializer};
const FORMAT: &'static str = "%s.%6f";
pub fn serialize<S>(date: &DateTime<Utc>, 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<DateTime<Utc>, 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(DateTime::<Utc>::from_naive_utc_and_offset(dt, Utc))
}
}
And Serialize/Deserialize using the #[serde(with="")]
option.
My question is: if there is an optional field in the web API, I cannot use this same mod so far if the value is Option<>
. So for example, if the payload can either be:
{"field1": "hello", "timestamp1": "1714521961.793749"}
or
{"field1": "hello", "field2": "bye", "timestamp1": "1714521961.793749", "timestamp2": "1714521961.793749"}
I can do:
#[derive(Serialize, Deserialize)]
pub struct Payload {
field1: String
field2: Option<String>
...
for the field parts, but I cannot do
#[serde(with="unix_timestamp")]
timestamp1: DateTime<Utc>
#[serde(with="unix_timestamp")]
timestamp2: Option<DateTime<Utc>>
}
It tells me that: expected Option<DateTime<Utc>>, found DateTime<Utc>
I can get around this by adding another mod, unix_timestamp_opt
, with the different return type, but is there a way to re use the same code for both?