(反)序列化RFC-3339时间戳与服务器到time-rs OffsetDateTime



我的目标是使用serde和time-rs将带有RFC-3339时间戳的对象从Json(反)序列化为Rust结构(反之亦然)。

我希望这个…

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);
}

…创建结构并显示时间戳作为输出,但是我得到…

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

我的依赖项是这样的:

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

根据time-rs crate的文档,这似乎是可能的,但我一定是遗漏了什么。

time的默认序列化格式是某种内部格式。如果您想要其他格式,您应该启用serde-well-known功能并使用serde模块来选择您想要的格式:

#[derive(Deserialize)]
pub struct DtoTest {
#[serde(with = "time::serde::rfc3339")]
pub timestamp: OffsetDateTime,
}

下面的解决方案是基于serde_with crate的。根据它的文档,它的目标是更加灵活和可组合。

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,
}

Cargo.toml文件应该有:

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

在下面的页面中列出了所有可用的De/Serialize转换。