Hi Community
The snippet below implements the ser / deserialization for protobuf Timestamp Package google.protobuf | Protocol Buffers | Google Developers
I wonder if I can deserialize the TImestamp from just timestamp string value, not JSON-like string.
My test is failed.
Thank you in advance!
use chrono::prelude::*;
use serde::de::{self, Deserialize, Deserializer, Visitor};
use serde::ser::{Serialize, Serializer};
use serde_json;
#[derive(Debug, PartialEq)]
struct Timestamp {
seconds: i64,
nanos: i32,
}
impl Serialize for Timestamp {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
DateTime::<Utc>::from_utc(
NaiveDateTime::from_timestamp(self.seconds, self.nanos as u32),
Utc,
)
.to_rfc3339()
.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Timestamp {
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
where
D: Deserializer<'de>,
{
struct TimestampVisitor;
impl<'de> Visitor<'de> for TimestampVisitor {
type Value = Timestamp;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("Timestamp in RFC3339 format")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
chrono::DateTime::parse_from_rfc3339(value)
.map(|dt| Timestamp{ seconds: dt.timestamp(), nanos: dt.timestamp_subsec_nanos() as i32})
.map_err(E::custom)
}
}
deserializer.deserialize_str(TimestampVisitor)
}
}
fn main() {
let ts = Timestamp {
seconds: 123456,
nanos: 123
};
println!(
"{:?} is {:?}",
ts,
serde_json::to_string(&ts)
);
let ts_string = "2021-12-27T07:00:00.000Z";
println!(
"{:?} is {:?}",
ts_string,
serde_json::from_str::<Timestamp>(ts_string).unwrap()
);
}
Output:
Timestamp { seconds: 123456, nanos: 123 } is Ok("\"1970-01-02T10:17:36.000000123+00:00\"")
Errors:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 3.40s
Running `target/debug/playground`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("invalid type: integer `2021`, expected Timestamp in RFC3339 format", line: 1, column: 4)', src/main.rs:69:54
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace