serde_secrecy/
lib.rs

1//! Serde support for [`secrecy`] types.
2
3use secrecy::{ExposeSecret as _, SecretString};
4use serde::Serializer;
5
6/// Enables serialization of [`secrecy::SecretString`] fields by exposing the inner string.
7///
8/// # Examples
9///
10/// ```
11/// # use serde::Serialize;
12/// # use secrecy::SecretString;
13/// #[derive(Debug, Serialize)]
14/// struct Login {
15///     #[serde(serialize_with = "serde_secrecy::expose_secret_string")]
16///     password: SecretString,
17/// }
18///
19/// let req = Login {
20///     password: SecretString::from("hunter2"),
21/// };
22///
23/// let json = serde_json::to_string(&req).unwrap();
24/// assert!(json.contains("hunter2"));
25/// ```
26pub fn expose_secret_string<S: Serializer>(
27    secret: &SecretString,
28    ser: S,
29) -> Result<S::Ok, S::Error> {
30    ser.serialize_str(secret.expose_secret())
31}
32
33#[cfg(test)]
34mod tests {
35    use serde::Serialize;
36
37    use super::*;
38
39    #[test]
40    fn serialize_secret_string() {
41        #[derive(Debug, Serialize)]
42        struct Login {
43            email: String,
44            #[serde(serialize_with = "expose_secret_string")]
45            password: SecretString,
46        }
47
48        let req = Login {
49            email: "foo@example.com".to_owned(),
50            password: SecretString::from("hunter2"),
51        };
52
53        let debug = format!("{req:?}");
54        let json = serde_json::to_string(&req).unwrap();
55
56        assert!(debug.contains("example.com"));
57        assert!(json.contains("example.com"));
58
59        assert!(!debug.contains("hunter2"));
60        assert!(json.contains("hunter2"));
61    }
62}