secure-serialize 0.1.0

A proc-macro for automatically redacting sensitive fields during serialization
Documentation

secure-serialize

A proc-macro crate that automatically redacts sensitive fields during serialization.

When a struct is derived with #[derive(SecureSerialize)], all fields marked with #[redact] will be replaced with "<redacted>" (or a custom string) when serialized via serde::Serialize. For cases where you need the real values (internal operations like config hot-reloading), the to_json_unredacted() method is available.

Example

use secure_serialize::SecureSerialize;
use serde::Deserialize;

#[derive(Deserialize, SecureSerialize)]
struct Config {
    pub host: String,

    /// This field will be redacted to "<redacted>" when serialized
    #[redact]
    pub api_key: String,

    /// This field will be redacted to "***" when serialized
    #[redact(with = "***")]
    pub password: String,
}

let config = Config {
    host: "localhost".to_string(),
    api_key: "secret123".to_string(),
    password: "my_password".to_string(),
};

// Serialized version has redacted fields
let serialized = serde_json::to_value(&config).unwrap();
assert_eq!(serialized["api_key"], "<redacted>");
assert_eq!(serialized["password"], "***");
assert_eq!(serialized["host"], "localhost");

// Unredacted version has all real values (internal use only!)
let unredacted = config.to_json_unredacted().unwrap();
assert_eq!(unredacted["api_key"], "secret123");
assert_eq!(unredacted["password"], "my_password");

Attributes

#[redact]

Mark a field as sensitive. When serialized, it will be replaced with "<redacted>".

#[derive(SecureSerialize)]
struct Config {
    #[redact]
    pub secret: String,
}

#[redact(with = "...")]

Mark a field as sensitive and specify a custom redaction string.

#[derive(SecureSerialize)]
struct Config {
    #[redact(with = "***")]
    pub password: String,
}

#[secure_serialize(debug)] and #[secure_serialize(display)]

Optional struct-level attributes (place them on the struct, next to derive):

  • debug — generates impl std::fmt::Debug where #[redact] fields show the redaction string instead of real values. Use this for {:?}, dbg!, and typical logging.
  • display — generates impl std::fmt::Display as compact JSON with the same redaction as serde_json::to_string (requires serde_json in your crate’s dependency graph, same as to_json_unredacted).

You can combine them: #[secure_serialize(debug, display)].

If you omit these, behavior stays as before: only Serialize redacts. #[derive(Debug)] alone still prints real secrets — opt in to #[secure_serialize(debug)] when you want safe Debug.

#[derive(Deserialize, SecureSerialize)]
#[secure_serialize(debug, display)]
struct Config {
    pub host: String,
    #[redact]
    pub api_key: String,
}

Trait Methods

  • redacted_keys() — Returns a static slice of all redacted field names.
  • to_json_unredacted() — Returns a JSON value with all real values (no redaction). Use this only for internal operations where you need actual values.
  • to_json_with_revealed_fields() — Same as normal JSON serialization, but you pass a list of redacted field names to expose with real values; all other redacted fields stay redacted.

⚠️ Warning: to_json_unredacted() exposes all sensitive data. Use it only internally, never expose its output to logs, APIs, or external systems.

⚠️ to_json_with_revealed_fields still exposes real values for every field you list. Use only in controlled contexts (for example internal tooling or selective debugging).