Personalizando a Serialização
Formate a saída JSON e de configuração com atributos de campo e contêiner do serde - nenhuma implementação manual é necessária para a maioria dos casos.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ApiUser {
user_id: u64,
#[serde(skip_serializing_if = "Option::is_none")]
nickname: Option<String>,
#[serde(default)]
active: bool,
}Quando usar isso: APIs externas usam nomes, campos opcionais ou layouts aninhados diferentes de suas structs Rust.
Exemplo de Trabalho
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct User {
user_id: u64,
#[serde(skip_serializing_if = "Option::is_none")]
display_name: Option<String>,
#[serde(default)]
role: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Envelope {
#[serde(flatten)]
user: User,
version: u32,
}
fn main() {
let u = User { user_id: 1, display_name: None, role: "member".into() };
let json = serde_json::to_string(&u).unwrap();
assert!(json.contains("userId"));
assert!(!json.contains("displayName"));
let env = Envelope { user: u, version: 2 };
let flat = serde_json::to_string(&env).unwrap();
assert!(flat.contains(r#""version":2"#));
assert!(flat.contains(r#""userId":1"#));
}O que isso demonstra:
rename_allmapeia chaves JSON snake_case do Rust para camelCase.skip_serializing_ifomite campos opcionaisNoneda saída.defaultpreenche chaves ausentes na desserialização.flattenmescla campos de struct aninhados no objeto pai.
Mergulho Profundo
Atributos de Alto Valor
| Atributo | Efeito |
|---|---|
rename / rename_all | Nomenclatura de chaves |
skip / skip_serializing | Omitir campos |
default | Chave ausente → Default::default() |
flatten | Inlinear chaves de struct aninhadas |
alias | Aceitar nomes de chave alternativos na desserialização |
with | Função de serialização personalizada para o tipo de campo |
Notas do Rust
mod ts {
use serde::{Deserializer, Serializer};
pub fn serialize<S: Serializer>(dt: &time::OffsetDateTime, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(&dt.format(&time::format_description::well_known::Rfc3339).unwrap())
}
}
#[serde(with = "ts")]
created_at: time::OffsetDateTime,Armadilhas
- Colisões de
flatten- Duas structs achatadas com os mesmos nomes de campo. Correção: Renomeie os campos ou aninhe explicitamente. skipsemdefault- A desserialização de dados antigos que não possuem novos campos gera erro. Correção: AdicionedefaultouOption.rename_allem enums - Afeta os nomes das variantes também - verifique a compatibilidade com OpenAPI. Correção: Testes de snapshot por formato.skip_serializing_ifemVecvazia - Pode ocultar arrays vazios intencionais. Correção: Useskip_serializing_if = "Vec::is_empty"apenas quando a API omitir listas vazias.- Erros de caminho de módulo
with- Assinatura incorreta no módulo personalizado. Correção: Copie o modelo da documentação do serde parawith,serialize_with.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Tipos DTO separados | API e modelos de domínio divergem muito | Overhead de mapeamento pequeno inaceitável |
crate serde_with | Tipos comuns como Duration | Um módulo with único é suficiente |
| Implementação manual | Controle total sobre a forma de transmissão | Atributos cobrem 90% dos casos |
FAQs
skip vs skip_serializing?
skip remove o campo em ambas as direções; skip_serializing afeta apenas a saída.
deserialize_with?
Função personalizada quando o formato de entrada difere do de saída.
deny_unknown_fields?
Análise rigorosa - rejeita chaves inesperadas.
transparent?
Newtype envolve a serialização interna sem chave extra.
bound attribute?
Relaxa os limites genéricos em implementações derivadas para tipos personalizados.
tag em enum?
Veja a página Enums & Tagging para os atributos tag, content.
serialize_none?
Emite null vs omite a chave - controle com skip_serializing_if.
múltiplos aliases de rename?
alias = "oldName" aceita chaves legadas ao desserializar.
flatten + enum?
Suportado com cuidado - teste o round-trip completamente.
sincronização OpenAPI?
Gere das mesmas structs com utoipa para evitar desvios.
Relacionado
- Noções Básicas de Serde - Introdução ao Derive
- Enums & Tagging - Atributos de Enum
- Serialização (De)personalizada - Implementações manuais
- JSON com serde_json - Formato de transmissão
- Melhores Práticas do Serde - Regras de compatibilidade
Versões da Pilha: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.