用serde将毫秒级时间戳字符串反序列化为DateTime

7

我从外部API收到一个毫秒级时间戳,作为JSON字符串属性。

{"time":"1526522699918"}

如何最好地使用Serde将毫秒级时间戳解析为字符串?

ts_milliseconds选项适用于整数类型的毫秒级时间戳,但在使用字符串时会引发错误。

示例 - Rust Playground

#[macro_use]
extern crate serde_derive;
extern crate chrono;
use chrono::serde::ts_milliseconds;
use chrono::{DateTime, Utc};

#[derive(Deserialize, Serialize)]
struct S {
    #[serde(with = "ts_milliseconds")]
    time: DateTime<Utc>,
}

fn main() {
    serde_json::from_str::<S>(r#"{"time":1526522699918}"#).unwrap(); // millisecond timestamp as a integer
    serde_json::from_str::<S>(r#"{"time":"1526522699918"}"#).unwrap(); // millisecond timestamp as an string
}

错误信息:
Error("invalid type: string \"1526522699918\", expected a unix timestamp in milliseconds", line: 1, column: 23)'

请见 https://serde.rs/string-or-struct.html。 - Stargateur
1个回答

9
可以使用来自serde_withTimestampMilliSeconds类型对序列化后的DateTime进行抽象,从而将其序列化为浮点数、整数或字符串,并且保留HTML标记。您需要启用serde_with中的chrono功能。
第一个参数(这里是String)配置序列化行为。对于String,这意味着DateTime将被序列化为包含Unix毫秒时间戳的字符串。
第二个参数(这里是Flexible)允许配置反序列化行为。 Flexible表示它可以从浮点数、整数和字符串反序列化,而不会返回错误。您可以使用它来运行问题中的main函数。另一个选项是Strict,它仅从第一个参数中反序列化格式。对于这个示例,这意味着它只会将时间作为字符串进行反序列化,但在遇到整数时会返回错误。
use ::chrono::{DateTime, Utc};
use serde_with::TimestampMilliSeconds;
use serde_with::formats::Flexible;

#[serde_with::serde_as]
#[derive(serde::Deserialize, serde::Serialize)]
struct S {
    #[serde_as(as = "TimestampMilliSeconds<String, Flexible>")]
    time: DateTime<Utc>,
}

fn main() {
    serde_json::from_str::<S>(r#"{"time":1526522699918}"#).unwrap(); // millisecond timestamp as a integer
    serde_json::from_str::<S>(r#"{"time":"1526522699918"}"#).unwrap(); // millisecond timestamp as an string
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接