Object Serialization in Rust: Overview of Libraries and Tools
Serialization is one of the fundamental processes in software development. It allows converting complex data structures (objects, structs, enums) into a sequential format convenient for storing on disk or transmitting over a network. The reverse process — deserialization — restores the original objects from this format. In the Rust language, this task is handled by an ecosystem centered around the Serde library (Serialization/Deserialization).
In this article, we will take a detailed look at how serialization works in Rust, what libraries exist for it, and how to use them in practice.
Why Serde?
Serde is not just a library, but a framework for serialization and deserialization. Its main feature is the separation into two parts:
- Serde Data Model — the core that defines how Rust data types are converted into an intermediate representation.
- Format Adapters — separate crates that work with specific formats (JSON, YAML, TOML, Bincode, MessagePack, and others).
This approach allows using the same code to work with different formats, changing only one line in Cargo.toml.
Setup and Basic Configuration
To get started, add the following dependencies to your Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"A key feature is using the #[derive(Serialize, Deserialize)] attribute. It automatically generates code for converting your structs:
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]struct User { id: u64, 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_pretty(&user).unwrap(); println!("JSON:{}", json);
// Deserialization back let deserialized: User = serde_json::from_str(&json).unwrap(); println!("Restored: {:?}", deserialized);}Working with Different Formats
Serde supports dozens of formats. Let's look at the most popular ones:
JSON (serde_json)
The most common format for web APIs. Human-readable, but takes up a lot of space.
// Serialization to stringlet json_str = serde_json::to_string(&data)?;
// Serialization to stream (file)let file = std::fs::File::create("data.json")?;let writer = std::io::BufWriter::new(file);serde_json::to_writer(writer, &data)?;
// Reading from filelet file = std::fs::File::open("data.json")?;let reader = std::io::BufReader::new(file);let data: MyStruct = serde_json::from_reader(reader)?;Bincode (bincode)
A binary format — compact and fast. Ideal for internal storage or transmission between Rust services.
// Cargo.toml: bincode = "1.3"
let encoded: Vec<u8> = bincode::serialize(&data)?;let decoded: MyStruct = bincode::deserialize(&encoded)?;YAML and TOML (serde_yaml, toml)
Used for configuration files. Human-readable, support comments (YAML).
// YAMLlet yaml = serde_yaml::to_string(&data)?;let data: MyStruct = serde_yaml::from_str(&yaml)?;
// TOML (popular in the Rust ecosystem)let toml = toml::to_string(&data)?;let data: MyStruct = toml::from_str(&toml)?;Advanced Features: Serde Attributes
Serde provides powerful attributes for fine-tuning serialization:
#[derive(Serialize, Deser Also in library
Database Migrations in C# (.NET): Entity Framework, FluentMigrator, and Other Approaches
Parsing HTML in Go (Golang): Libraries and Code Examples