Serde: Framework de Serialização e Desserialização Rust

Serde é uma biblioteca central no ecossistema Rust, fornecendo um framework eficiente e versátil para serialização e desserialização. Seu nome deriva da combinação de "Serialização" e "Desserialização."

Características Principais

  • Versatilidade: Suporta múltiplos formatos de dados como JSON, YAML, TOML, MessagePack e mais.
  • Abstração de Custo Zero: Código gerado em tempo de compilação é tão eficiente quanto código escrito manualmente.
  • Flexibilidade: Permite personalização do comportamento de serialização e desserialização.
  • Tipagem Forte: Aproveita o sistema de tipos do Rust para garantir integridade dos dados.
  • Ampla Adoção: Serve como biblioteca padrão para troca de dados no ecossistema Rust.

Como Funciona

O núcleo do Serde está em seu design de Representação Intermediária (IR), que divide os processos de serialização e desserialização em duas etapas:

  1. Serialização: Converte estruturas de dados Rust em uma representação intermediária genérica, depois para o formato alvo.
  2. Desserialização: Converte formatos de entrada na representação intermediária genérica, depois em estruturas de dados Rust.

Este design permite adicionar novos formatos de dados sem modificar aplicações que utilizam o Serde.

Uso Básico

Configurando Dependências

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" # Ou outras bibliotecas de formato como serde_yaml, toml, etc.

Usando Macros Derive

O uso mais comum envolve macros derive para implementar automaticamente traits de serialização e desserialização para structs:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Ponto {
    x: i32,
    y: i32,
}

fn main() {
    let ponto = Ponto { x: 1, y: 2 };

    // Converter Ponto para string JSON
    let serializado = serde_json::to_string(&ponto).unwrap();
    println!("Resultado serializado: {}", serializado); // Saída: {"x":1,"y":2}

    // Converter string JSON de volta para Ponto
    let desserializado: Ponto = serde_json::from_str(&serializado).unwrap();
    println!("Resultado desserializado: {:?}", desserializado); // Saída: Ponto { x: 1, y: 2 }
}

Personalização com Atributos

Serde fornece um conjunto rico de atributos para personalizar comportamento de serialização:

#[derive(Serialize, Deserialize, Debug)]
struct Usuario {
    #[serde(rename = "user_id")]
    id: u64,
    
    #[serde(default)]
    nome: String,
    
    #[serde(skip_serializing_if = "Option::is_none")]
    email: Option<String>,
    
    #[serde(skip)]
    dados_temporarios: usize,
}

Formatos de Dados Suportados

Serde integra-se com vários formatos de dados, cada um com sua própria crate:

  • serde_json: Formato JSON
  • serde_yaml: Formato YAML
  • toml: Formato TOML
  • bincode: Formato binário
  • postcard: Formato binário otimizado para espaço
  • rmp/rmp-serde: Formato MessagePack
  • ciborium: Formato CBOR
  • ...e outros formatos

Uso Avançado

Implementação Manual de Traits

Para requisitos especiais, você pode implementar manualmente as traits Serialize e Deserialize:

use serde::{Serialize, Serializer, Deserialize, Deserializer};

struct MeuTipo {
    // Campos...
}

impl Serialize for MeuTipo {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // Lógica de serialização personalizada
    }
}

impl<'de> Deserialize<'de> for MeuTipo {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        // Lógica de desserialização personalizada
    }
}

Mapeamento de Tipos

Você pode criar mapeamentos entre diferentes representações de dados:

#[derive(Serialize, Deserialize)]
#[serde(remote = "chrono::DateTime<chrono::Utc>")]
struct DateTimeRef {
    #[serde(with = "chrono::serde::ts_seconds")]
    pub inner: chrono::DateTime<chrono::Utc>,
}

Aprendizado e Recursos

Serde é uma biblioteca rica em recursos, e este artigo cobre apenas o básico. Para aproveitar totalmente o Serde, recomenda-se:

  1. Visitar a documentação oficial do Serde para APIs detalhadas e exemplos.
  2. Consultar o repositório GitHub para código-fonte e atualizações mais recentes.

Conclusão

Como biblioteca fundamental no ecossistema Rust, Serde fornece ferramentas poderosas e flexíveis para troca de dados. Dominando o Serde, você pode lidar sem esforço com várias necessidades de intercâmbio de dados, tornando suas aplicações mais robustas e interoperáveis.