Object Serialization in Rust: Complete Guide to the serde Library and Data Formats
Serialization is the process of converting data structures or objects into a format that can be saved to a file, transmitted over a network, or cached. In the Rust language, this task is solved elegantly and efficiently using the serde library (Serialization/Deserialization). In this article, we will take a detailed look at how serialization works in Rust, which data formats are supported, and how to choose the right tool for your project.
What is serde and why is it the de facto standard?
serde is a framework for serializing and deserializing data structures in Rust. It is not tied to a specific format — you can use JSON, Bincode, YAML, TOML, MessagePack, CBOR, and many others. The main idea: you describe your structure once, and serde automatically generates code for working with any format through the Serialize and Deserialize trait system.
Advantages of serde:
- Maximum performance — code is generated at compile time (zero-cost abstraction)
- Type safety — format mismatch errors are caught at compile time
- Support for complex structures: enums, vectors, hash maps, nested objects
- Customization through attributes
Installation and basic setup
Add the following dependencies to Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"bincode = "1.3"The key point is the "derive" feature for serde. Without it, you would have to manually implement the Serialize and Deserialize traits.
Simple example: serialization to JSON
JSON is the most popular format for web applications and APIs. Let's look at a basic example:
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: "Alexey".to_string(), email: "alex@example.com".to_string(), is_active: true, };
// Serialization to JSON let json = serde_json::to_string(&user).unwrap(); println!("JSON: {}", json);
// Deserialization from JSON let deserialized: User = serde_json::from_str(&json).unwrap(); println!("Deserialized: {:?}", deserialized);}Output:
JSON: {"id":42,"name":"Alexey","email":"alex@example.com","is_active":true}Deserialized: User { id: 42, name: "Alexey", email: "alex@example.com", is_active: true }Binary serialization with bincode
For high-performance applications (games, real-time systems, databases), a compact binary format is often required. bincode is one of the best 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!["sword".into(), "potion".into()], checkpoint: (120.5, -34.8), };
// Serialization to binary format let binary = bincode::serialize(&state).unwrap(); println!("Binary size: {} bytes", binary.len());
// Deserialization let restored: GameState = bincode::deserialize(&binary).unwrap(); println!("Restored: {:?}", restored);}Bincode provides gains in data size and processing speed compared to JSON. For example, a structure with 4 fields will take about 40 bytes versus 100+ in JSON.
Working with YAML and TOML
For configuration files
Also in library
Sending Email in Kotlin: Libraries and Code Examples
MetricsKit — Swift Application Monitoring (iOS/macOS)
Dependency Injection Container for Swift (iOS/macOS): Swinject
R.swift for Swift: Complete Guide with Examples