【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"
}
相关推荐
小灰灰搞电子21 小时前
Rust可以取代C++么?
开发语言·c++·rust
百锦再1 天前
京东云鼎入驻方案解读——通往协同的“高架桥”与“快速路”
android·java·python·rust·django·restful·京东云
异步思考者1 天前
Rust实战:一个内存消息队列的 Trait 驱动开发
rust
受之以蒙1 天前
智能目标检测:用 Rust + dora-rs + yolo 构建“机器之眼”
人工智能·笔记·rust
熬了夜的程序员1 天前
【Rust学习之路】第 0 章:理解 Rust 的核心哲学
开发语言·学习·rust
EniacCheng1 天前
【RUST】学习笔记-环境搭建
笔记·学习·rust
禅思院1 天前
在win10上配置 Rust以及修改默认位置问题
开发语言·前端·后端·rust·cargo·mingw64·cargo安装位置
shandianchengzi1 天前
【记录】Rust|Rust开发相关的7个VSCode插件的介绍和推荐指数(2025年)
开发语言·vscode·rust
JPX-NO1 天前
Rust + Rocket + Diesel构建的RESTful API示例(CRUD)
开发语言·rust·restful
林太白1 天前
Rust01-认识安装
开发语言·后端·rust