Serde is the de facto serialization and deserialization framework for Rust, enabling fast, zero-copy, compile-time data format translation.
Serde (a portmanteau of SERializing and DEserializing) is the foundational serialization framework for the Rust programming language. Rather than relying on runtime reflection or dynamic type inspection—which would incur runtime CPU and memory overhead—Serde operates via compile-time procedural macros (#[derive(Serialize, Deserialize)]). It decouples Rust data structures from target data formats, allowing any custom data model to seamlessly serialize to and deserialize from JSON, TOML, YAML, MessagePack, Bincode, or Protocol Buffers without intermediate runtime allocations.
Generate idiomatic Rust struct definitions with Serde attributes using our JSON to Rust Struct Converter or convert between config formats with our TOML Converter.
| Specification | Details |
|---|---|
| Creator & Lead Maintainer | David Tolnay (dtolnay) |
| Current Standard | Serde v1.0.x |
| Core Crates | serde (Data model), serde_derive (Proc macros), serde_json (JSON adapter) |
| Cargo Dependency | serde = { version = "1.0", features = ["derive"] } |
| Type Safety | 100% sound compile-time type enforcement with Option<T> nullability |
| Allocation Model | Zero-copy deserialization via borrowed references (&'a str, Cow<'a, str>) or owned allocations (String) |
| Ecosystem Integrations | Tokio, Actix Web, Axum, Reqwest, Diesel, SQLx, SurrealDB, Polars |
| Supported Formats | JSON, TOML, YAML, CBOR, MessagePack, Bincode, Postcard, RON, FlexBuffers |
Serde establishes a clean abstraction boundary between Data Structures (your application's Rust types) and Data Formats (JSON, TOML, binary).
The architecture consists of three interconnected layers:
Serializer / Deserializer Traits: Implemented by data format crates (e.g., serde_json::Deserializer).Serialize / Deserialize Traits: Implemented by Rust data types (typically auto-generated via #[derive(...)]).Visitor Trait: Implemented by deserializers to receive primitive values from format parsers without creating intermediate objects.use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserAccount {
pub id: u64,
pub username: String,
pub email: String,
pub is_active: bool,
pub phone_number: Option<String>,
}
Serde provides powerful compile-time attribute macros to bridge protocol discrepancies:
| Attribute | Scope | Purpose | Example |
|---|---|---|---|
#[serde(rename_all = "...")] |
Struct / Enum | Renames all fields to camelCase, snake_case, kebab-case, or SCREAMING_SNAKE_CASE. |
#[serde(rename_all = "camelCase")] |
#[serde(rename = "...")] |
Field / Variant | Renames an individual field or enum variant to match a specific external string. | #[serde(rename = "x-api-key")] |
#[serde(default)] |
Field / Struct | Falls back to Default::default() if the field is missing from the input. |
#[serde(default)] |
#[serde(skip_serializing_if = "...")] |
Field | Omits the field during serialization if the given predicate returns true. |
#[serde(skip_serializing_if = "Option::is_none")] |
#[serde(untagged)] |
Enum | Deserializes untagged polymorphic JSON without discriminator fields. | #[serde(untagged)] |
#[serde(flatten)] |
Field | Flattens the contents of a nested struct into the parent container. | #[serde(flatten)] |
serde_jsonuse serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct OrderEvent {
pub order_id: String,
pub customer_id: u64,
pub amount: f64,
#[serde(default)]
pub is_priority: bool,
pub notes: Option<String>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let raw_json = r#"
{
"order_id": "ord_9902",
"customer_id": 48201,
"amount": 149.95,
"notes": null
}
"#;
// Deserialization directly into typed struct:
let order: OrderEvent = serde_json::from_str(raw_json)?;
println!("Order #{} for customer {} (Priority: {})", order.order_id, order.customer_id, order.is_priority);
// Serialization back to formatted JSON:
let json_output = serde_json::to_string_pretty(&order)?;
println!("Serialized JSON:\n{}", json_output);
Ok(())
}
For ultra-high-throughput stream processing, Serde can borrow string slices (&'a str) directly from the input buffer without heap allocations:
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct FastLogEntry<'a> {
pub level: &'a str,
pub message: &'a str,
pub timestamp: &'a str,
}
fn process_log<'a>(buffer: &'a str) -> Result<FastLogEntry<'a>, serde_json::Error> {
// No memory allocation for strings:
serde_json::from_str::<FastLogEntry<'a>>(buffer)
}
Serde relies on Rust's monomorphization and compiler inlining. Because derive macros generate specialized parsing code at compile time for each concrete struct, there are no runtime vtables, boxing, or reflection lookups. The compiler optimizes serialization logic directly into machine code instructions.
Option<T> and #[serde(default)] in Serde?Option<T> indicates that a field may be null in JSON or completely omitted from the payload, deserializing to None in both cases. #[serde(default)] instructs Serde that if the field is missing, it should populate the struct field with its standard Default::default() value (such as 0 for integer fields or false for booleans).
Yes. If a JSON payload contains arbitrary key-value pairs, Serde deserializes it into std::collections::HashMap<String, serde_json::Value> or std::collections::BTreeMap<String, Value>. If you need to embed untyped fields alongside structured fields, annotate a map field with #[serde(flatten)].
Instead of manually typing out Rust structs and field annotations, paste your JSON response into our JSON to Rust Struct Converter to generate compile-ready structs with derive macros and case renaming in seconds.
Free, browser-based utilities to test, generate, and inspect Serde Serialization & Deserialization Framework for Rust payloads directly.
Convert JSON into idiomatic Rust structs with Serde Serialize and Deserialize derive macros.
Convert JSON to C# classes with System.Text.Json or Newtonsoft serialization.
Convert JSON to TypeScript interfaces or type aliases instantly.
Convert JSON to Zod schema definitions with automatic TypeScript type inference.
Repair and fix malformed JSON data from AI outputs, API responses, and copy-paste.
Convert between TOML and JSON formats with syntax validation, key sorting, and auto-direction detection.
Convert between JSON and YAML with validation, formatting, and multi-document support.