derive
- Rust course
- Intermediate
- Lesson 102/115
- 4 min
Auto-implement with #[derive(Serialize, Deserialize)].
derive
#[derive(Serialize, Deserialize)] automatically generates code that walks field by field. For this to work, all field types must implement these traits too; the standard types (String, numbers, Vec, Option, HashMap) all do:
#[derive(Serialize, Deserialize)]
struct Raf {
ad: String,
kitaplar: Vec<Kitap>, // Kitap must derive too
etiketler: Vec<String>,
}Enums can be derived too; variants are written as {"Ekle":{"metin":".."}} by default.
Composability through a trait
The power of derive is composability: each type only knows its own part, and nested structures just work. We can see the same idea with a small trait:
trait JsonYaz {
fn json(&self) -> String;
}
impl JsonYaz for i32 {
fn json(&self) -> String { self.to_string() }
}
impl<T: JsonYaz> JsonYaz for Vec<T> {
fn json(&self) -> String {
let ic: Vec<String> = self.iter().map(|x| x.json()).collect();
format!("[{}]", ic.join(","))
}
}The Vec<T> implementation works without knowing how the inner type is written.
Practice Composable writer
Implement the JsonYaz trait for i32, &str (quoted) and Vec<T: JsonYaz>. Print the results for vec![1, 2, 3] and vec!["a", "b"] separated by a space.
Starter code
fn main() {
// buraya yaz
}Sample solution
trait JsonYaz {
fn json(&self) -> String;
}
impl JsonYaz for i32 {
fn json(&self) -> String {
self.to_string()
}
}
impl JsonYaz for &str {
fn json(&self) -> String {
format!("\"{}\"", self)
}
}
impl<T: JsonYaz> JsonYaz for Vec<T> {
fn json(&self) -> String {
let ic: Vec<String> = self.iter().map(|x| x.json()).collect();
format!("[{}]", ic.join(","))
}
}
fn main() {
println!("{} {}", vec![1, 2, 3].json(), vec!["a", "b"].json());
}Expected output
[1,2,3] ["a","b"]
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What happens if a field's type doesn't implement <code>Serialize</code>?
- The derive gives a compile error Correct answer
- The field is skipped
- null is written
- Runtime error
Explanation: The error tells which field is the problem. Either that type must derive too, or the field is left out with #[serde(skip)].
2 Blanket implementation
impl<T: ____> JsonYaz for Vec<T> {
fn json(&self) -> String { .. }
}
impl<T: JsonYaz> JsonYaz for Vec<T> {
fn json(&self) -> String { .. }
}
Explanation: Vec<T> is JsonYaz as long as its elements are JsonYaz.
3 Value and JSON
| Term | Meaning |
|---|---|
42 |
42 |
"a" |
"a" |
vec![1, 2, 3] |
[1,2,3] |
vec!["a", "b"] |
["a","b"] |