(De)serialize RFC-3339 timestamp with serde to time-rs OffsetDateTime
Asked Answered
C

2

6

My goal is to (de)serialize objects with RFC-3339 timestamps from Json to Rust structs (and vice versa) using serde and time-rs.

I would expect this ...

use serde::Deserialize;
use time::{OffsetDateTime};

#[derive(Deserialize)]
pub struct DtoTest {
    pub timestamp: OffsetDateTime,
}

fn main() {
    let deserialization_result = serde_json::from_str::<DtoTest>("{\"timestamp\": \"2022-07-08T09:10:11Z\"}");
    let dto = deserialization_result.expect("This should not panic");
    println!("{}", dto.timestamp);
}

... to create the struct and display the timestamp as the output, but I get ...

thread 'main' panicked at 'This should not panic: Error("invalid type: string \"2022-07-08T09:10:11Z\", expected an `OffsetDateTime`", line: 1, column: 36)', src/main.rs:12:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

My dependencies look like this:

[dependencies]
serde = { version = "1.0.138", features = ["derive"] }
serde_json = "1.0.82"
time = { version = "0.3.11", features = ["serde"] }

According to the documentation of the time-rs crate, this seems to be possible but I must be missing something.

Chortle answered 12/7, 2022 at 19:45 Comment(0)
K
9

The default serialization format for time is some internal format. If you want other formats, you should enable the serde-well-known feature and use the serde module to choose the format you want:

#[derive(Deserialize)]
pub struct DtoTest {
    #[serde(with = "time::serde::rfc3339")]
    pub timestamp: OffsetDateTime,
}
Kingkingbird answered 13/7, 2022 at 3:0 Comment(0)
M
-1

The solution below is based on the serde_with crate. As per its documentation, it aims to be more flexible and composable.

use serde_with::serde_as;
use time::OffsetDateTime;
use time::format_description::well_known::Rfc3339;

#[serde_as]
#[derive(Deserialize)]
pub struct DtoTest {
    #[serde_as(as = "Rfc3339")]
    pub timestamp: OffsetDateTime,
}

And the Cargo.toml file should have:

[dependencies]
serde_with = { version = "2", features = ["time_0_3"] }

At the following page are listed all De/Serialize transformations available.

Maurita answered 10/1, 2023 at 22:22 Comment(1)
This doesn't work. serde_as requires code specifically for it.Kingkingbird

© 2022 - 2024 — McMap. All rights reserved.