how do I (de)serialize an integer number of seconds since the Unix epoch? #100
-
What is the proper way to deserialize a Unix time stamp? Here's the relevant line (converting from #[serde(rename = "deprecatedAt", skip_serializing_if = "Option::is_none", default)]
pub deprecated_at: Option<Timestamp>, Which results in:
Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 4 replies
-
What did you use for Chrono? |
Beta Was this translation helpful? Give feedback.
-
use chrono::{serde::ts_seconds_option, DateTime, Utc};
...
#[serde(
rename = "deprecatedAt",
skip_serializing_if = "Option::is_none",
with = "ts_seconds_option",
default
)] |
Beta Was this translation helpful? Give feedback.
-
OK, so here's what I came up with: use jiff::Timestamp;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
struct Data {
#[serde(with = "ser_de")]
timestamp: Option<Timestamp>,
}
fn main() -> anyhow::Result<()> {
let data = r#"{"timestamp": 1517644800 }"#;
let got: Data = serde_json::from_str(&data)?;
dbg!(&got);
Ok(())
}
mod ser_de {
use serde::Deserialize;
pub(super) fn serialize<S: serde::Serializer>(
timestamp: &Option<jiff::Timestamp>,
se: S,
) -> Result<S::Ok, S::Error> {
match *timestamp {
None => se.serialize_none(),
Some(ts) => se.serialize_i64(ts.as_second()),
}
}
pub(super) fn deserialize<'de, D: serde::Deserializer<'de>>(
de: D,
) -> Result<Option<jiff::Timestamp>, D::Error> {
let second = Option::<i64>::deserialize(de)?;
let Some(second) = second else { return Ok(None) };
jiff::Timestamp::from_second(second)
.map_err(serde::de::Error::custom)
.map(Some)
}
} So basically, you'll want to copy the This actually took me about 10 minutes to write. And I've written things like this before. My guess is that this is a common enough use case that Jiff should probably provide something out of the box for this... |
Beta Was this translation helpful? Give feedback.
-
All righty, use jiff::Timestamp;
struct Record {
#[serde(with = "jiff::fmt::serde::timestamp::second::optional")]
timestamp: Option<Timestamp>,
}
let json = r#"{"timestamp":1517644800}"#;
let got: Record = serde_json::from_str(&json)?;
assert_eq!(got.timestamp, Some(Timestamp::from_second(1517644800)?));
assert_eq!(serde_json::to_string(&got)?, json); For other examples and docs, see: https://docs.rs/jiff/0.1.11/jiff/fmt/serde/index.html |
Beta Was this translation helpful? Give feedback.
-
Fantastic! That's working great for me. |
Beta Was this translation helpful? Give feedback.
All righty,
jiff 0.1.11
has a much better answer for this:For other examples and docs, see: https://docs.rs/jiff/0.1.11/jiff/fmt/serde/index.html