<skill_overview> Serialize and deserialize Rust types safely and predictably
Designing request/response DTOs Parsing JSON or config files Customizing field names or defaults Handling versioned schemas
Serde GitHub Serde Docs
</skill_overview>
Use #[derive(Serialize, Deserialize)] for DTOs Keep DTOs separate from domain entities Prefer strongly typed structs over Value
<field_attributes>
Use #[serde(rename_all = "camelCase")] for JSON APIs Use #[serde(default)] for optional fields Use #[serde(skip_serializing_if = "Option::is_none")] for omitting nulls Use #[serde(flatten)] to merge nested fields
#[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct UserDto { #[serde(default)] display_name: String, #[serde(skip_serializing_if = "Option::is_none")] email: Option, }
</field_attributes> <validation_and_schema>
Use #[serde(deny_unknown_fields)] for strict inputs Version payloads via enums or tagged variants
</validation_and_schema> <custom_serialization>
Use serialize_with/deserialize_with only when necessary Prefer newtype wrappers for custom formats
</custom_serialization> <anti_patterns> Avoid untagged enums for public APIs Avoid mapping enums to raw strings manually Avoid serde_json::Value for core flows </anti_patterns>