Serde
Enum Tags
In Serde, a tag is discriminator data that identifies which enum variant a serialized value represents.
The default enum representation is externally tagged:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
enum Event {
Login { user: String },
Logout { user: String },
}
{ "Login": { "user": "alice" } }
Use #[serde(tag = "...")] when the serialized format should carry the
variant name in a field:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Event {
Login { user: String },
Logout { user: String },
}
{ "type": "Login", "user": "alice" }
Here, type is the tag field and Login is the variant value.
Lower-Case Tags
Use rename_all = "lowercase" on the enum to serialize and deserialize enum
variant names as lower-case strings:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
enum Event {
Login { user: String },
Logout { user: String },
}
{ "type": "login", "user": "alice" }
For multi-word variant names, lowercase removes word boundaries:
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
enum Event {
UserLogin { user: String },
}
{ "type": "userlogin", "user": "alice" }
Prefer snake_case when the serialized variant name should preserve word
boundaries:
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
enum Event {
UserLogin { user: String },
}
{ "type": "user_login", "user": "alice" }
Use rename for a one-off variant name:
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Event {
#[serde(rename = "login")]
Login { user: String },
#[serde(rename = "logout")]
Logout { user: String },
}
Common Representations
Internally tagged enums place the tag beside the variant fields:
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
enum Event {
Login { user: String },
}
{ "type": "login", "user": "alice" }
Adjacently tagged enums separate the tag from the variant payload:
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "data", rename_all = "lowercase")]
enum Event {
Login { user: String },
}
{ "type": "login", "data": { "user": "alice" } }
Untagged enums omit the tag. Serde chooses a variant by matching the input shape, so this is best reserved for compatibility with formats that do not carry a discriminator:
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum Event {
Login { user: String },
Count(u64),
}