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 SecureSerialize;
use Deserialize;
let config = Config ;
// Serialized version has redacted fields
let serialized = to_value.unwrap;
assert_eq!;
assert_eq!;
assert_eq!;
// Unredacted version has all real values (internal use only!)
let unredacted = config.to_json_unredacted.unwrap;
assert_eq!;
assert_eq!;
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— generatesimpl std::fmt::Debugwhere#[redact]fields show the redaction string instead of real values. Use this for{:?},dbg!, and typical logging.display— generatesimpl std::fmt::Displayas compact JSON with the same redaction asserde_json::to_string(requiresserde_jsonin your crate’s dependency graph, same asto_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).