Skip to content

Commit b554142

Browse files
authored
RUST-1987 Add serde helper module for Option<DateTime> (#482)
1 parent 0ed3635 commit b554142

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

src/serde_helpers.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ pub use chrono_datetime_as_bson_datetime::{
1717
deserialize as deserialize_chrono_datetime_from_bson_datetime,
1818
serialize as serialize_chrono_datetime_as_bson_datetime,
1919
};
20+
#[cfg(feature = "chrono-0_4")]
21+
#[doc(inline)]
22+
pub use chrono_datetime_as_bson_datetime_optional::{
23+
deserialize as deserialize_chrono_datetime_from_bson_datetime_optional,
24+
serialize as serialize_chrono_datetime_as_bson_datetime_optional,
25+
};
2026
#[doc(inline)]
2127
pub use hex_string_as_object_id::{
2228
deserialize as deserialize_hex_string_from_object_id,
@@ -307,6 +313,51 @@ pub mod chrono_datetime_as_bson_datetime {
307313
}
308314
}
309315

316+
/// Contains functions to serialize an [`Option<chrono::DateTime>`] as an
317+
/// [`Option<crate::DateTime>`] and deserialize an [`Option<chrono::DateTime>`] from an
318+
/// [`Option<crate::DateTime>`].
319+
///
320+
/// ```rust
321+
/// # #[cfg(feature = "chrono-0_4")]
322+
/// # {
323+
/// # use serde::{Serialize, Deserialize};
324+
/// # use bson::serde_helpers::chrono_datetime_as_bson_datetime_optional;
325+
/// #[derive(Serialize, Deserialize)]
326+
/// struct Event {
327+
/// #[serde(with = "chrono_datetime_as_bson_datetime_optional")]
328+
/// pub date: Option<chrono::DateTime<chrono::Utc>>,
329+
/// }
330+
/// # }
331+
/// ```
332+
#[cfg(feature = "chrono-0_4")]
333+
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
334+
pub mod chrono_datetime_as_bson_datetime_optional {
335+
use crate::DateTime;
336+
use chrono::Utc;
337+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
338+
use std::result::Result;
339+
340+
/// Deserializes a [`chrono::DateTime`] from a [`crate::DateTime`].
341+
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
342+
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<chrono::DateTime<Utc>>, D::Error>
343+
where
344+
D: Deserializer<'de>,
345+
{
346+
let val = Option::deserialize(deserializer)?.map(|datetime: DateTime| datetime.to_chrono());
347+
Ok(val)
348+
}
349+
350+
/// Serializes a [`Option<chrono::DateTime>`] as a [`Option<crate::DateTime>`].
351+
#[cfg_attr(docsrs, doc(cfg(feature = "chrono-0_4")))]
352+
pub fn serialize<S: Serializer>(
353+
val: &Option<chrono::DateTime<Utc>>,
354+
serializer: S,
355+
) -> Result<S::Ok, S::Error> {
356+
let datetime = val.map(DateTime::from_chrono);
357+
datetime.serialize(serializer)
358+
}
359+
}
360+
310361
/// Contains functions to serialize an RFC 3339 (ISO 8601) formatted string as a [`crate::DateTime`]
311362
/// and deserialize an RFC 3339 (ISO 8601) formatted string from a [`crate::DateTime`].
312363
///

src/tests/serde.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,59 @@ fn test_datetime_helpers() {
866866
assert_eq!(b.date, expected);
867867
}
868868

869+
#[cfg(feature = "chrono-0_4")]
870+
{
871+
use std::str::FromStr;
872+
#[derive(Deserialize, Serialize)]
873+
struct B {
874+
#[serde(with = "serde_helpers::chrono_datetime_as_bson_datetime_optional")]
875+
pub date: Option<chrono::DateTime<chrono::Utc>>,
876+
}
877+
878+
let date = r#"
879+
{
880+
"date": {
881+
"$date": {
882+
"$numberLong": "1591700287095"
883+
}
884+
}
885+
}"#;
886+
let json: serde_json::Value = serde_json::from_str(date).unwrap();
887+
let b: B = serde_json::from_value(json).unwrap();
888+
let expected: Option<chrono::DateTime<chrono::Utc>> =
889+
Some(chrono::DateTime::from_str("2020-06-09 10:58:07.095 UTC").unwrap());
890+
assert_eq!(b.date, expected);
891+
let doc = to_document(&b).unwrap();
892+
assert_eq!(
893+
Some(doc.get_datetime("date").unwrap().to_chrono()),
894+
expected
895+
);
896+
let b: B = from_document(doc).unwrap();
897+
assert_eq!(b.date, expected);
898+
}
899+
900+
#[cfg(feature = "chrono-0_4")]
901+
{
902+
#[derive(Deserialize, Serialize)]
903+
struct B {
904+
#[serde(with = "serde_helpers::chrono_datetime_as_bson_datetime_optional")]
905+
pub date: Option<chrono::DateTime<chrono::Utc>>,
906+
}
907+
908+
let date = r#"
909+
{
910+
"date": null
911+
}"#;
912+
let json: serde_json::Value = serde_json::from_str(date).unwrap();
913+
let b: B = serde_json::from_value(json).unwrap();
914+
let expected = None;
915+
assert_eq!(b.date, expected);
916+
let doc = to_document(&b).unwrap();
917+
assert_eq!(None, expected);
918+
let b: B = from_document(doc).unwrap();
919+
assert_eq!(b.date, expected);
920+
}
921+
869922
#[derive(Deserialize, Serialize)]
870923
struct C {
871924
#[serde(with = "rfc3339_string_as_bson_datetime")]

0 commit comments

Comments
 (0)