Einleitung: Warum ist JSON in Rust wichtig?
\n\nJSON (JavaScript Object Notation) bleibt eines der beliebtesten Formate für den Datenaustausch zwischen Diensten, Konfigurationsdateien und APIs. Im Rust-Ökosystem wird die Arbeit mit JSON durch die leistungsstarke Crate serde_json realisiert, die zusammen mit dem Framework serde eine elegante und sichere Möglichkeit zur Umwandlung von Datenstrukturen bietet.
Im Gegensatz zu dynamischen Sprachen erfordert Rust eine explizite Typbeschreibung, was auf den ersten Blick kompliziert erscheinen mag. In der Praxis bietet dies jedoch eine unglaubliche Zuverlässigkeit: Sie werden niemals einen unerwarteten null-Wert oder ein Feld mit falschem Typ zur Laufzeit erhalten. In diesem Artikel behandeln wir das Parsing (Deserialisierung) und die Serialisierung von JSON anhand konkreter Beispiele, die Sie sofort in realen Projekten anwenden können.
1. Projekteinrichtung und Installation der Abhängigkeiten
\n\nBevor wir Code schreiben, fügen wir die erforderlichen Crates in Cargo.toml hinzu:
[dependencies]\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\n\nDie Crate serde mit dem Flag derive ermöglicht die automatische Generierung von Code für die Serialisierung und Deserialisierung unserer Strukturen. serde_json ist direkt für die Umwandlung in/aus JSON zuständig.
Importieren wir alles Notwendige in main.rs:
use serde::{Deserialize, Serialize};\nuse serde_json::Result;\n\n2. Serialisierung: Rust-Struktur in JSON umwandeln
\n\nSerialisierung ist der Prozess der Umwandlung eines Rust-Objekts in einen JSON-String. Betrachten wir ein klassisches Beispiel mit Benutzerdaten.
\n\nDeklaration der Struktur
\n\nFügen wir die Annotationen #[derive(Serialize, Deserialize)] zu unserer Struktur hinzu:
#[derive(Debug, Serialize, Deserialize)]\nstruct User {\n id: u32,\n name: String,\n email: String,\n is_active: bool,\n tags: Vec<String>,\n}\n\nErstellen einer Instanz und Serialisierung
\n\nJetzt erstellen wir ein Objekt und wandeln es in JSON um:
\n\nfn main() -> Result<()> {\n let user = User {\n id: 42,\n name: "Alexej".to_string(),\n email: "alex@example.com".to_string(),\n is_active: true,\n tags: vec!["rust".to_string(), "backend".to_string()],\n };\n\n // Serialisierung in einen JSON-String\n let json_string = serde_json::to_string(&user)?;\n println!("{}", json_string);\n\n // Hübsche (pretty) Serialisierung\n let pretty_json = serde_json::to_string_pretty(&user)?;\n println!("{}", pretty_json);\n\n Ok(())\n}\n\nErgebnis der Ausführung:
\n\n{"id":42,"name":"Alexej","email":"alex@example.com","is_active":true,"tags":["rust","backend"]}\n\n{\n "id": 42,\n "name": "Alexej",\n "email": "alex@example.com",\n "is_active": true,\n "tags": [\n "rust",\n "backend"\n ]\n}\n\nBeachten Sie: to_string_pretty fügt Einrückungen und Zeilenumbrüche hinzu – ideal für Konfigurationsdateien oder Logs.
3. Parsing (Deserialisierung): Von JSON zur Rust-Struktur
\n\nDeserialisierung ist der umgekehrte Prozess: Wir erhalten einen JSON-String und wandeln ihn in eine typisierte Rust-Struktur um.
\n\nParsing aus einem String
\n\nfn parse_user_from_json(json_str: &str) -> Result<User> {\n let user: User = serde_json::from_str(json_str)?;\n Ok(user)\n}\n\nfn main() -> Result<()> {\n let data = r#"\n {\n "id": 101,\n "name": "Maria",\n "email": "maria@example.com",\n "is_active": false,\n "tags": ["python", "data-science"]\n }\n "#;\n\n let user = parse_user_from_json(data)?;\n println!("Benutzer: {:?}", user);\n println!("Name: {}", user.name);\n println!("Aktiv: {}", user.is_active);\n\n Ok(())\n}\n\nWenn das JSON nicht der Struktur entspricht (z.B.