【ISO8601库】Serde 集成模块详解(serde.rs文件)

概述

这个模块为 ISO8601 日期时间类型提供了 Serde 序列化和反序列化支持,使其能够与 JSON 等格式无缝集成。

模块结构

模块分为四个子模块,分别处理不同的 ISO8601 类型:

  • date - 日期序列化
  • time - 时间序列化
  • datetime - 日期时间序列化
  • duration - 时间段序列化

核心实现模式

1. 序列化实现 (Serialize)

rust 复制代码
impl Serialize for crate::Date {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

工作原理

  • 调用类型的 to_string() 方法转换为 ISO8601 字符串
  • 使用序列化器的 serialize_str() 方法输出字符串

2. 反序列化实现 (Deserialize)

rust 复制代码
impl<'de> Deserialize<'de> for crate::Date {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(DateVisitor)
    }
}

工作原理

  • 委托给自定义的 Visitor 处理字符串反序列化
  • 使用 deserialize_str() 方法处理字符串输入

3. Visitor 模式

rust 复制代码
struct DateVisitor;
impl<'de> Visitor<'de> for DateVisitor {
    type Value = crate::Date;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "a string that follows iso8601 date format")
    }

    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        match Self::Value::from_str(s) {
            Ok(p) => Ok(p),
            Err(_) => Err(de::Error::invalid_value(de::Unexpected::Str(s), &self)),
        }
    }
}

Visitor 职责

  • expecting(): 提供错误消息中显示的类型期望描述
  • visit_str(): 实际处理字符串解析,使用类型的 from_str 方法

各类型具体实现

Date 类型 (日期)

格式 : "2023-02-10"

  • 序列化:日期 → "2023-02-10"
  • 反序列化:"2023-02-10" → 日期对象

Time 类型 (时间)

格式 : "18:12:15""18:12:15.0+00:00"

  • 支持带时区和毫秒的扩展格式
  • 测试显示支持简化和完整格式

DateTime 类型 (日期时间)

格式 : "2023-02-10T18:12:15""2023-02-10T18:12:15.0+00:00"

  • 支持多种精度级别
  • 测试验证了完整格式和简化格式(无秒数)

Duration 类型 (时间段)

格式 : "P1Y2M3DT4H5M6S" (ISO8601 持续时间格式)

  • P 表示周期开始
  • Y 年, M 月, D
  • T 时间部分开始
  • H 小时, M 分钟, S

错误处理

反序列化错误

rust 复制代码
Err(de::Error::invalid_value(de::Unexpected::Str(s), &self))

from_str 解析失败时,返回标准的 Serde 错误:

  • invalid_value: 表示输入值无效
  • de::Unexpected::Str(s): 包装实际输入值
  • &self: 提供期望的类型信息(通过 expecting 方法)

测试验证

每个子模块都包含完整的序列化往返测试:

序列化测试

rust 复制代码
#[test]
fn serialize() {
    let date_json = r#""2023-02-10""#;
    let date = crate::date("2023-02-10").unwrap();
    let serialized_date = serde_json::to_string(&date).unwrap();
    assert_eq!(serialized_date, date_json);
}

反序列化测试

rust 复制代码
#[test]
fn deserialize() {
    let date_json = r#""2023-02-10""#;
    let date = crate::date("2023-02-10").unwrap();
    let deserialized_date = serde_json::from_str::<crate::Date>(date_json).unwrap();
    assert_eq!(deserialized_date, date);
}

设计特点

  1. 字符串为基础: 所有类型都序列化为人类可读的 ISO8601 字符串
  2. 格式保持: 序列化后的格式符合 ISO8601 标准
  3. 错误友好: 提供清晰的错误信息和类型期望
  4. 往返安全: 序列化后再反序列化能得到原始对象
  5. 格式灵活性: 支持 ISO8601 的各种格式变体

使用示例

json 复制代码
{
  "date": "2023-02-10",
  "time": "18:12:15", 
  "datetime": "2023-02-10T18:12:15",
  "duration": "P1Y2M3DT4H5M6S"
}
相关推荐
空白诗10 小时前
mdcat 在 HarmonyOS 上的构建与适配
后端·安全·华为·rust·harmonyos
Rust语言中文社区12 小时前
【Rust日报】Dioxus 用起来有趣吗?
开发语言·后端·rust
小灰灰搞电子12 小时前
Rust Slint实现颜色选择器源码分享
开发语言·后端·rust
Source.Liu14 小时前
【Chrono库】Unix-like 系统时区处理实现(src/offset/local/unix.rs)
rust·time
I***261517 小时前
数据库操作与数据管理——Rust 与 SQLite 的集成
数据库·rust·sqlite
元Y亨H20 小时前
RustDesk 自建远程桌面服务器部署指南
rust
@大迁世界1 天前
相信我兄弟:Cloudflare Rust 的 .unwrap() 方法在 330 多个数据中心引发了恐慌
开发语言·后端·rust
2***B4491 天前
Rust在系统编程中的内存安全
开发语言·后端·rust
U***e631 天前
Rust错误处理最佳实践
开发语言·后端·rust
疏狂难除2 天前
随便玩玩lldb (二)
开发语言·后端·rust