Serde : Cadre de sérialisation et désérialisation Rust

serdeserde

Serde est une bibliothèque centrale de l'écosystème Rust, offrant un cadre de sérialisation et désérialisation performant et universel. Son nom provient de la combinaison de "Serialization" et "Deserialization".

Principales caractéristiques

  • Universalité : Prend en charge de multiples formats de données comme JSON, YAML, TOML, MessagePack, etc.
  • Abstraction sans coût : Le code généré à la compilation est aussi efficace qu'un code écrit manuellement
  • Flexibilité : Permet de personnaliser les comportements de sérialisation et désérialisation
  • Typage fort : Utilise le système de types de Rust pour garantir l'intégrité des données
  • Large adoption : Devenue la bibliothèque standard pour les échanges de données dans l'écosystème Rust

Fonctionnement

Le cœur de Serde repose sur son design de représentation intermédiaire (Intermediate Representation), qui divise le processus en deux étapes :

  1. Sérialisation : Convertit les structures Rust en représentation intermédiaire, puis vers le format cible
  2. Désérialisation : Convertit le format d'entrée en représentation intermédiaire, puis vers des structures Rust

Cette conception permet d'ajouter de nouveaux formats sans modifier les applications utilisant Serde.

Utilisation de base

Configuration des dépendances

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" # ou d'autres bibliothèques comme serde_yaml, toml, etc.

Utilisation des macros dérivées

L'usage le plus courant consiste à utiliser les macros dérivées pour implémenter automatiquement les traits Serialize et Deserialize :

use serde::{Serialize, Deserialize};

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

fn main() {
    let point = Point { x: 1, y: 2 };

    // Conversion du Point en chaîne JSON
    let serialized = serde_json::to_string(&point).unwrap();
    println!("Résultat sérialisé : {}", serialized); // Sortie : {"x":1,"y":2}

    // Reconversion de la chaîne JSON en Point
    let deserialized: Point = serde_json::from_str(&serialized).unwrap();
    println!("Résultat désérialisé : {:?}", deserialized); // Sortie : Point { x: 1, y: 2 }
}

Personnalisation par attributs

Serde offre de riches attributs pour personnaliser le comportement :

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

Formats supportés

Serde s'intègre avec de nombreux formats, chacun ayant son propre crate :

  • serde_json : Format JSON
  • serde_yaml : Format YAML
  • toml : Format TOML
  • bincode : Format binaire
  • postcard : Format binaire optimisé
  • rmp/rmp-serde : Format MessagePack
  • ciborium : Format CBOR
  • ...et d'autres formats

Utilisation avancée

Implémentation manuelle des traits

Pour des besoins spécifiques, on peut implémenter manuellement les traits Serialize et Deserialize :

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

struct MyType {
    // champs...
}

impl Serialize for MyType {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // Logique de sérialisation personnalisée
    }
}

impl<'de> Deserialize<'de> for MyType {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        // Logique de désérialisation personnalisée
    }
}

Correspondance de types

Permet de créer des correspondances entre différentes représentations :

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

Apprentissage et ressources

Serde est une bibliothèque riche en fonctionnalités. Pour en tirer pleinement parti :

  1. Consultez la documentation officielle pour des API détaillées et des exemples
  2. Visitez le dépôt GitHub pour le code source et les mises à jour

Conclusion

Serde, en tant que bibliothèque fondamentale de l'écosystème Rust, fournit des outils puissants et flexibles pour les échanges de données. En maîtrisant Serde, vous pouvez facilement gérer divers formats d'échange, rendant vos applications plus robustes et interopérables.