概述
这个模块为 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);
}
设计特点
- 字符串为基础: 所有类型都序列化为人类可读的 ISO8601 字符串
- 格式保持: 序列化后的格式符合 ISO8601 标准
- 错误友好: 提供清晰的错误信息和类型期望
- 往返安全: 序列化后再反序列化能得到原始对象
- 格式灵活性: 支持 ISO8601 的各种格式变体
使用示例
json
{
"date": "2023-02-10",
"time": "18:12:15",
"datetime": "2023-02-10T18:12:15",
"duration": "P1Y2M3DT4H5M6S"
}