From 1a1cb5c93e8b31bdc9bacf65976916f0acc02417 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 2 Nov 2026 19:26:40 +0200 Subject: [PATCH] docs: explain optional string trimming behavior --- crates/detrim/src/string.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/crates/detrim/src/string.rs b/crates/detrim/src/string.rs index e8a3253..42ac54e 100644 --- a/crates/detrim/src/string.rs +++ b/crates/detrim/src/string.rs @@ -13,6 +13,30 @@ pub fn string<'de, D: Deserializer<'de>>(de: D) -> Result { } /// Trims an optional string during deserialization. +/// +/// A null value becomes `None`. A string that is empty after trimming becomes +/// `Some("")`. Use [`crate::option_string_non_empty`] to return `None` for empty strings. +/// +/// Add `#[serde(default)]` to accept a missing field as `None`. +/// +/// # Examples +/// +/// ``` +/// #[derive(serde::Deserialize)] +/// struct Form { +/// #[serde(default, deserialize_with = "detrim::option_string")] +/// name: Option, +/// } +/// +/// let form: Form = serde_json::from_str(r#"{}"#).unwrap(); +/// assert_eq!(form.name, None); +/// +/// let form: Form = serde_json::from_str(r#"{"name": null}"#).unwrap(); +/// assert_eq!(form.name, None); +/// +/// let form: Form = serde_json::from_str(r#"{"name": " "}"#).unwrap(); +/// assert_eq!(form.name.as_deref(), Some("")); +/// ``` pub fn option_string<'de, D: Deserializer<'de>>(de: D) -> Result, D::Error> { let val = Option::::deserialize(de)?; Ok(val.map(|val| val.trim().to_owned()))