Rust
derive
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.
Exercise 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.
Show example 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());
}
Test yourself
-
What happens if a field's type doesn't implement <code>Serialize</code>?
- The derive gives a compile error
- The field is skipped
- null is written
- Runtime error
Show answer
The derive gives a compile error — The error tells which field is the problem. Either that type must derive too, or the field is left out with #[serde(skip)].
-
Blanket implementation
impl<T: ____> JsonYaz for Vec<T> {
fn json(&self) -> String { .. }
}
Show answer
impl<T: JsonYaz> JsonYaz for Vec<T> {
fn json(&self) -> String { .. }
}
-
Value and JSON
- 42
- 42
- "a"
- "a"
- vec![1, 2, 3]
- [1,2,3]
- vec!["a", "b"]
- ["a","b"]
Next lesson: JSON