【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"
}
相关推荐
星释2 小时前
Rust 练习册 :Proverb与字符串处理
开发语言·后端·rust
星释4 小时前
Rust 练习册 :Pig Latin与语言游戏
游戏·rust·c#
2301_795167204 小时前
玩转Rust高级应用 如何让让运算符支持自定义类型,通过运算符重载的方式是针对自定义类型吗?
开发语言·后端·算法·安全·rust
ftpeak6 小时前
《Rust+Slint:跨平台GUI应用》第八章 窗体
开发语言·ui·rust·slint
百锦再9 小时前
第10章 错误处理
java·git·ai·rust·go·错误·pathon
2301_7951672011 小时前
玩转Rust高级应用. ToOwned trait 提供的是一种更“泛化”的Clone 的功能,Clone一般是从&T类型变量创造一个新的T类型变量
开发语言·后端·rust
星释11 小时前
Rust 练习册 :Phone Number与电话号码处理
开发语言·机器学习·rust
2301_7965125212 小时前
Rust编程学习 - 问号运算符会return一个Result 类型,但是如何使用main函数中使用问号运算符
开发语言·学习·算法·rust
星释13 小时前
Rust 练习册 :Poker与扑克牌游戏
开发语言·游戏·rust