A procedural macro to generate field/variant name enums and constants for structs and enums using Serde, respecting #[serde(rename = "...")] and #[serde(rename_all = "...")].
- Automatically generate a
const SERDE_FIELDS: &'static [&'static str]array containing the serialized names of all non-skipped struct fields or enum variants. - Generate an enum named
{TypeName}SerdeFieldfor all non-skipped fields or variants. - Generated enum variants match Rust field names (PascalCase) for structs and original variant names for enums. They are annotated with
#[serde(rename = "...")], matching the serialized names of the original type, and are (de)serializable. - For struct-like enum variants, generate nested enums named
{EnumName}{VariantName}SerdeFieldfor the variant's non-skipped fields. - Provides convenient methods and trait implementations:
as_str() -> &'static strDisplayimplementationFrom<Enum>andFrom<&Enum>for&'static strTryFrom<&str>andTryFrom<String>with custom errorInvalid{TypeName}SerdeFieldFromStrimplementationAsRef<str>for ergonomic usage
- Supports skipped fields/variants via
#[serde(skip)]and renaming via#[serde(rename = "...")]. - Fully respects type-level
#[serde(rename_all = "...")], and enum#[serde(rename_all_fields = "...")]for struct-like variant fields.
Add this to your Cargo.toml:
[dependencies]
serde = { version = "1.0", features = ["serde_derive"] }
serde_fields = "0.1"use serde::{Serialize, Deserialize};
use serde_fields::SerdeField;
#[derive(Serialize, Deserialize, SerdeField)]
#[serde(rename_all = "camelCase")]
struct User {
user_id: u32,
#[serde(rename = "eMail")]
email: String,
foo_bar: String,
}
// Access serialized field names as a slice
assert_eq!(User::SERDE_FIELDS, &["userId", "eMail", "fooBar"]);
// Use the generated enum
let field = UserSerdeField::UserId;
assert_eq!(field.as_str(), "userId");
assert_eq!(field.to_string(), "userId");
// Parse enum from string
let parsed: UserSerdeField = "userId".parse().unwrap();
assert_eq!(parsed, UserSerdeField::UserId);
// Convert enum to string slice
let name: &str = UserSerdeField::Email.into();
assert_eq!(name, "eMail");
// Serialize
let serialized = serde_json::to_string(&UserSerdeField::FooBar).unwrap();
assert_eq!("\"fooBar\"", serialized);
#[derive(Serialize, Deserialize, SerdeField)]
#[serde(rename_all = "kebab-case", rename_all_fields = "camelCase")]
enum Event {
UserCreated,
#[serde(rename = "deleted")]
UserDeleted,
PayloadReceived {
payload_id: u32,
#[serde(rename = "data")]
payload_data: String,
},
}
assert_eq!(
Event::SERDE_FIELDS,
&["user-created", "deleted", "payload-received"]
);
assert_eq!(EventSerdeField::UserCreated.as_str(), "user-created");
assert_eq!(
EventPayloadReceivedSerdeField::SERDE_FIELDS,
&["payloadId", "data"]
);
assert_eq!(
EventPayloadReceivedSerdeField::PayloadId.as_str(),
"payloadId"
);