serde Basics
9 examples to get you started with serde - 6 basic and 3 intermediate.
Prerequisites
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"- Serde 1.0 is the de facto serialization framework for Rust.
- Add format crates (
serde_json,toml, etc.) per wire format.
Basic Examples
1. Derive Serialize
Turn a struct into JSON.
use serde::Serialize;
#[derive(Serialize)]
struct User { id: u64, name: String }
let u = User { id: 1, name: "Ada".into() };
let json = serde_json::to_string(&u).unwrap();#[derive(Serialize)]generates the trait impl.- Field names become JSON keys by default.
to_stringallocates;to_vecfor bytes.
Related: JSON with serde_json - parsing and
Value
2. Derive Deserialize
Parse JSON into a struct.
use serde::Deserialize;
#[derive(Deserialize)]
struct Point { x: i32, y: i32 }
let p: Point = serde_json::from_str(r#"{"x":1,"y":2}"#).unwrap();- Missing fields error unless marked
Optionordefault. - Type mismatches return descriptive serde errors.
- Prefer owned
Stringfor untrusted input.
3. Both Traits
Round-trip types need both derives.
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Config { debug: bool }- Add
Debugfor test assertions. Clonewhen storing configs in state.
4. Vec and Collections
Serialize lists and maps.
#[derive(Serialize)]
struct Batch { items: Vec<String> }
let json = serde_json::to_string(&Batch { items: vec!["a".into()] }).unwrap();Vec,HashMap,BTreeMapwork out of the box.- Empty collections serialize as
[]or{}.
5. Option Fields
Optional JSON keys map to Option.
#[derive(Deserialize)]
struct Profile { bio: Option<String> }- Missing key deserializes to
None. nullin JSON also maps toNoneforOption<T>.
6. Enum Unit Variants
Simple tagged enums.
#[derive(Serialize, Deserialize)]
enum Status { Active, Inactive }- Default enum encoding is externally tagged.
- See Enums & Tagging for other shapes.
Related: Enums & Tagging - representation options
Intermediate Examples
7. #[serde(rename)]
Match foreign API camelCase.
#[derive(Deserialize)]
struct ApiUser {
#[serde(rename = "userId")]
id: u64,
}- Rename individual fields without changing Rust names.
rename_all = "camelCase"on the struct for all fields.
Related: Customizing Serialization - more attributes
8. #[serde(default)]
Fill missing fields with defaults.
#[derive(Deserialize)]
struct Settings {
#[serde(default)]
retries: u32,
}- Uses
Default::default()for the field type. - Common for forward-compatible API evolution.
9. Generic Types
Serde supports generics with bounds.
#[derive(Serialize, Deserialize)]
struct Page<T> { items: Vec<T> }
#[derive(Serialize, Deserialize)]
struct Item { id: u64 }Tmust implementSerialize/Deserialize.- Works with
Vec<T>,Option<T>, nested generics.
Related: Custom (De)serialization - manual impls
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.