You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Serde中将Map的整数值反序列化为SystemTime类型?

问题描述

我有如下JSON文件,希望将其反序列化为Rust结构体:

{
  "name": "Manuel",
  "friends": {
    "id1": 1703692376,
    ...
  }
  ...
}

其中friends字段包含ID和秒级时间戳。我已创建如下可正常运行的Rust结构体,但希望将friends字段改为HashMap<String, SystemTime>类型,把JSON中的整数值转换为SystemTime类型,请问能否通过Serde实现这一需求?

use std::collections::HashMap;
use serde::{Deserialize, Serialize};

#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct MyStruct{
    name: String,
    friends: HashMap<String, i64>
}
解决方案

完全可以通过Serde实现,核心是为SystemTime添加序列化/反序列化的适配逻辑,以下是两种可行方案:

方案一:手动实现自定义序列化逻辑

通过Serde的Deserialize和Serialize trait,手动完成整数时间戳与SystemTime的转换:

  1. 导入所需依赖:
use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::Error;
  1. 为SystemTime实现序列化和反序列化逻辑:
// 反序列化:秒级时间戳转SystemTime
impl<'de> Deserialize<'de> for SystemTime {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let timestamp = i64::deserialize(deserializer)?;
        UNIX_EPOCH.checked_add(std::time::Duration::from_secs(timestamp as u64))
            .ok_or_else(|| D::Error::custom("无效时间戳:超出SystemTime范围"))
    }
}

// 序列化:SystemTime转秒级时间戳(若需要将结构体序列化为JSON则添加此实现)
impl Serialize for SystemTime {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.duration_since(UNIX_EPOCH)
            .map(|d| d.as_secs() as i64)
            .map_err(|e| S::Error::custom(format!("SystemTime转时间戳失败:{}", e)))
    }
}
  1. 修改结构体使用目标类型:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MyStruct {
    name: String,
    friends: HashMap<String, SystemTime>,
}

方案二:使用serde_with库简化实现

借助serde_with库提供的现成适配逻辑,无需手动编写大量代码:

  1. 在Cargo.toml中添加依赖:
serde_with = "3.0"
  1. 利用库中Timestamp模块完成转换:
use std::collections::HashMap;
use std::time::SystemTime;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use serde_with::Timestamp;

#[serde_as]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MyStruct {
    name: String,
    // 指定以秒级时间戳格式序列化/反序列化SystemTime
    #[serde_as(as = "HashMap<String, Timestamp<i64, serde_with::format::Seconds>>")]
    friends: HashMap<String, SystemTime>,
}

如果你的时间戳是毫秒级,只需将Seconds替换为Milliseconds即可,serde_with支持多种时间戳精度格式。

内容的提问来源于stack exchange,提问作者Manuelarte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:52:19