rust-serde
Skill0 starsChanged 35 days agoMITView on GitHub
Use when serializing/deserializing Rust data.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- po4yka/rust-skillstheir own version, first seen Nov 2, 2026
- dawidpereira/rust-skillstheir own version, first seen Mar 22, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- po4yka/rust-skills★ 5same name
- dawidpereira/rust-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository15 other files it gives its agents.
- AGENTS.mdAGENTS.md
- rustoriaSkill
- rust-debuggingSkill
- rust-dependenciesSkill
- rust-fundamentalsSkill
- rust-axumSkill
- rust-clapSkill
- rust-dieselSkill
- rust-ratatuiSkill
- rust-rayonSkill
- rust-tokioSkill
- rust-productionSkill
- rust-code-auditSkill
- rust-stdSkill
- rust-unsafe-checkerSkill
The file
Files
Serde — Serialization Framework for Rust
Overview
Serde is a framework for serializing and deserializing Rust data structures efficiently and generically. It supports JSON, TOML, MessagePack, CBOR, YAML, and many more formats.
Installation
[dependencies]
serde = { version = "1", features = ["derive"] } # 1.0.2xx series
serde_json = "1" # JSON
toml = "1" # TOML (1.x line; 0.8 still works but is the previous major)
rmp-serde = "1" # MessagePack
ciborium = "0.2" # CBOR
# chrono = { version = "0.4", features = ["serde"] } # if you serialize DateTimeYAML warning: neither YAML serde adapter is a safe long-term bet.
serde_yamlis archived (0.9.34+deprecated) andserde_ymlis itself now marked deprecated/unmaintained on crates.io (its releases forward to thenoyalibcrate). For new projects prefer JSON or TOML; if you must have YAML, evaluatenoyalibdirectly and pin what you verify.
Core Concepts
1. Basic Derive
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
// Serialize to JSON
let json = serde_json::to_string(&point).unwrap();
println!("Serialized: {}", json); // {"x":1,"y":2}
// Deserialize from JSON
let deserialized: Point = serde_json::from_str(&json).unwrap();
println!("Deserialized: {:?}", deserialized);
}2. Field Attributes
use chrono::{DateTime, Utc}; // chrono = { version = "0.4", features = ["serde"] }
use serde::{Deserialize, Serialize};
use serde_json::Value; // serde_json = "1"
use std::collections::HashMap;
#[derive(Serialize, Deserialize)]
struct User {
#[serde(rename = "user_id")]
id: u64,
#[serde(default)]
name: String,
#[serde(skip_serializing_if = "Option::is_none")]
email: Option<String>,
// Deserializes as String::default(); the field type must implement Default
#[serde(skip)]
password: String,
#[serde(rename(serialize = "createdAt", deserialize = "created_at"))]
created_at: DateTime<Utc>,
#[serde(default)]
metadata: HashMap<String, Value>,
}3. Container Attributes
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct User {
first_name: String,
last_name: String,
}
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum Message {
Text { content: String },
Image { url: String, width: u32 },
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Value {
Int(i64),
Float(f64),
Str(String),
}4. Custom Serialization
use serde::{Deserialize, Deserializer, Serialize, Serializer};
struct Celsius(f64);
impl Serialize for Celsius {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
serializer.serialize_f64(self.0)
}
}
impl<'de> Deserialize<'de> for Celsius {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
let value = f64::deserialize(deserializer)?;
Ok(Celsius(value))
}
}5. Custom Field Serialization
use serde::{Deserialize, Serialize};
use std::time::Duration;
mod milliseconds {
use serde::{Deserialize, Deserializer, Serializer};
use std::time::Duration;
pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
serializer.serialize_u64(duration.as_millis() as u64)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where D: Deserializer<'de> {
let millis = u64::deserialize(deserializer)?;
Ok(Duration::from_millis(millis))
}
}
#[derive(Serialize, Deserialize)]
struct Event {
#[serde(with = "milliseconds")]
timestamp: Duration,
}6. Formats
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let point = Point { x: 1, y: 2 };
// JSON (serde_json)
let json = serde_json::to_string(&point)?;
let json_pretty = serde_json::to_string_pretty(&point)?;
let back: Point = serde_json::from_str(&json)?;
// also: from_reader(reader), from_slice(&bytes)
assert_eq!(back, point);
println!("{json_pretty}");
// TOML (toml)
let toml_str = toml::to_string(&point)?;
let back: Point = toml::from_str(&toml_str)?;
assert_eq!(back, point);
// YAML - both serde_yaml and serde_yml are deprecated on crates.io (see YAML warning
// above); prefer JSON/TOML. Shown for reading legacy files only.
let yaml = serde_yml::to_string(&point)?;
let back: Point = serde_yml::from_str(&yaml)?;
assert_eq!(back, point);
// MessagePack (rmp-serde)
let bytes = rmp_serde::to_vec(&point)?;
let back: Point = rmp_serde::from_slice(&bytes)?;
assert_eq!(back, point);
Ok(())
}7. Enums
Four representations — pick one per enum (these are alternatives, not meant to coexist in one file):
use serde::{Deserialize, Serialize};
use serde_json::Value;
// Externally tagged (default)
#[derive(Serialize, Deserialize)]
enum Message {
Request { id: u64, method: String, params: Vec<Value> },
Response { id: u64, result: Value },
}// Internally tagged
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
enum Message {
Request { id: u64, method: String },
Response { id: u64, result: Value },
}// Adjacently tagged
#[derive(Serialize, Deserialize)]
#[serde(tag = "t", content = "c")]
enum Message {
Request { id: u64, method: String },
Response { id: u64, result: Value },
}// Untagged — tried in order; first variant that matches wins
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Value {
Int(i64),
Float(f64),
Str(String),
}8. Generic Types
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct ApiResponse<T> {
data: T,
status: String,
}
#[derive(Serialize, Deserialize)]
struct Paginated<T> {
items: Vec<T>,
total: u64,
page: u64,
}9. Remote Derive (for external types)
with and remote solve different problems:
with = "module"— use a module'sserialize/deserializefunctions for one field.remote = "path"— deriveSerialize/Deserializefor a type from another crate you don't own, by mirroring its definition. The generated...Deftype is then referenced from fields withwith.
use serde::{Deserialize, Serialize};
// Imagine `External` lives in another crate and has no serde impls.
mod external_crate {
pub struct External {
pub a: i32,
pub b: String,
}
}
use external_crate::External;
// Mirror the external type's fields, pointed at the real type:
#[derive(Serialize, Deserialize)]
#[serde(remote = "External")]
struct ExternalDef {
a: i32,
b: String,
}
// Then apply it to fields with `with`:
#[derive(Serialize, Deserialize)]
struct Wrapper {
name: String,
#[serde(with = "ExternalDef")]
external: External,
}
fn main() -> serde_json::Result<()> {
let w = Wrapper {
name: "demo".into(),
external: External { a: 1, b: "x".into() },
};
let json = serde_json::to_string(&w)?;
println!("{json}");
Ok(())
}10. Best Practices
- Use
#[serde(default)]for backward-compatible deserialization - Use
skip_serializing_ifto omit empty fields - Use
rename_allfor consistent naming conventions - Use
withmodule for custom field serialization - Use
try_fromfor validation during deserialization - Use
flattenfor embedding structs - Use
borrowfor zero-copy deserialization:&'de str - Use
serde_json::Valuefor dynamic JSON
When to Use Serde
- API request/response serialization
- Configuration file parsing
- Database row mapping
- Message queue serialization
- Any data format conversion
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

