Sérialisation d'objets en Rust : guide complet sur la bibliothèque serde et les formats de données
La sérialisation est le processus de conversion de structures de données ou d'objets en un format qui peut être sauvegardé dans un fichier, transmis sur un réseau ou mis en cache. En langage Rust, cette tâche est résolue de manière élégante et efficace grâce à la bibliothèque serde (Serialization/Deserialization). Dans cet article, nous allons détailler comment fonctionne la sérialisation en Rust, quels formats de données sont pris en charge et comment choisir l'outil adapté à votre projet.
Qu'est-ce que serde et pourquoi est-ce la norme de facto ?
serde est un framework de sérialisation et de désérialisation de structures de données en Rust. Il n'est pas lié à un format spécifique — vous pouvez utiliser JSON, Bincode, YAML, TOML, MessagePack, CBOR et bien d'autres. L'idée principale : vous décrivez votre structure une seule fois, et serde génère automatiquement le code pour travailler avec n'importe quel format via le système de traits Serialize et Deserialize.
Avantages de serde :
- Performances maximales — le code est généré à la compilation (zero-cost abstraction)
- Sécurité des types — les erreurs de non-concordance des formats sont détectées à la compilation
- Prise en charge des structures complexes : enum, vecteurs, tables de hachage, objets imbriqués
- Possibilité de personnalisation via des attributs
Installation et configuration de base
Ajoutez les dépendances suivantes dans Cargo.toml :
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"bincode = "1.3"Point clé — la fonctionnalité "derive" pour serde. Sans elle, vous devrez implémenter manuellement les traits Serialize et Deserialize.
Exemple simple : sérialisation en JSON
JSON est le format le plus populaire pour les applications web et les API. Voici un exemple de base :
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct User { id: u32, name: String, email: String, is_active: bool,}
fn main() { let user = User { id: 42, name: "Alexeï".to_string(), email: "alex@example.com".to_string(), is_active: true, };
// Sérialisation en JSON let json = serde_json::to_string(&user).unwrap(); println!("JSON : {}", json);
// Désérialisation depuis JSON let deserialized: User = serde_json::from_str(&json).unwrap(); println!("Désérialisé : {:?}", deserialized);}Sortie :
JSON : {"id":42,"name":"Alexeï","email":"alex@example.com","is_active":true}Désérialisé : User { id: 42, name: "Alexeï", email: "alex@example.com", is_active: true }Sérialisation binaire avec bincode
Pour les applications haute performance (jeux, systèmes temps réel, bases de données), un format binaire compact est souvent nécessaire. bincode est l'une des meilleures options :
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct GameState { level: u16, health: f32, inventory: Vec<String>, checkpoint: (f64, f64),}
fn main() { let state = GameState { level: 5, health: 87.5, inventory: vec!["épée".into(), "potion".into()], checkpoint: (120.5, -34.8), };
// Sérialisation en format binaire let binary = bincode::serialize(&state).unwrap(); println!("Taille binaire : {} octets", binary.len());
// Désérialisation let restored: GameState = bincode::deserialize(&binary).unwrap(); println!("Restauré : {:?}", restored);}Bincode offre un gain en taille de données et en vitesse de traitement par rapport à JSON. Par exemple, une structure de 4 champs occupera environ 40 octets contre 100+ en JSON.
Travailler avec YAML et TOML
Pour les fichiers de configuration