如何将Option<Vec<DateTime>>字段序列化为BSON?
解决Rust中可选
DateTime向量的BSON序列化问题 你遇到的问题是因为bson::serde_helpers::chrono_datetime_as_bson_datetime这个序列化辅助函数仅针对单个DateTime<Utc>类型设计,但你的字段是Option<Vec<DateTime<Utc>>>,类型不匹配导致serde派生宏抛出类型错误。
我们需要自定义一个serde辅助模块,专门处理Option<Vec<DateTime<Utc>>>类型,内部复用bson提供的单个DateTime序列化逻辑来处理向量中的每个元素。
完整代码示例
use chrono::{DateTime, Utc}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use bson::{self, serde_helpers::chrono_datetime_as_bson_datetime}; // 自定义serde辅助模块,处理Option<Vec<DateTime<Utc>>> mod bson_vec_datetime_helpers { use super::*; /// 序列化Option<Vec<DateTime<Utc>>>为BSON日期数组 pub fn serialize<S>(vec: &Option<Vec<DateTime<Utc>>>, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { match vec { Some(dates) => { // 逐个转换每个DateTime为BSON日期 let bson_dates: Result<Vec<_>, _> = dates .iter() .map(|dt| chrono_datetime_as_bson_datetime::serialize(dt, serializer.clone())) .collect(); bson_dates?.serialize(serializer) } None => None.serialize(serializer), } } /// 从BSON日期数组反序列化为Option<Vec<DateTime<Utc>>> pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<DateTime<Utc>>>, D::Error> where D: Deserializer<'de>, { // 先反序列化为Option<Vec<BSON DateTime>> let bson_dates: Option<Vec<bson::DateTime>> = Option::deserialize(deserializer)?; // 逐个转换为chrono DateTime,处理可能的错误 bson_dates .map(|dates| { dates .into_iter() .map(|bson_dt| chrono_datetime_as_bson_datetime::deserialize(&bson_dt)) .collect::<Result<Vec<_>, _>>() }) .transpose() .map_err(serde::de::Error::custom) } } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Test { #[serde(with = "bson_vec_datetime_helpers")] pub time_period: Option<Vec<DateTime<Utc>>> }
说明
- 自定义的
bson_vec_datetime_helpers模块中,serialize函数会先检查Option是否有值:- 若存在向量,则遍历每个
DateTime<Utc>,用bson官方的辅助函数转换为BSON日期,再序列化整个向量 - 若为None,则直接序列化None
- 若存在向量,则遍历每个
deserialize函数则反向操作:先读取Option包裹的BSON日期数组,再逐个转换为chrono::DateTime<Utc>,并正确传递转换过程中的错误- 不需要额外修改你的
Cargo.toml依赖配置,保持原有配置即可
内容的提问来源于stack exchange,提问作者terett
相关产品推荐
相关产品推荐

