CodeBlanks Logo Icon CodeBlanks

Özet - Serde

serde_json ve derive'ı birleştirerek bir config okuyucu yazarsın.

Serde özeti

#[derive(Serialize, Deserialize)] veri yapısını biçimden bağımsız tanımlar; biçimi serde_json gibi bir crate sağlar (to_string, from_str). Adlar rename/rename_all ile eşlenir. Eksik alanlar Option ya da #[serde(default)] ile tolere edilir; skip_serializing_if boş alanları atlar. Okuma her zaman Result döndürür ve hata mesajı eksik ya da hatalı alanı söyler.

Gidiş dönüş

Bir ayar türünü yazıp aynı metinden geri okuyan iki fonksiyon:

#[derive(Debug, PartialEq)]
struct Ayar {
    port: u16,
    hata_ayikla: bool,
}

impl Ayar {
    fn json(&self) -> String {
        format!("{{\"port\":{},\"hata_ayikla\":{}}}", self.port, self.hata_ayikla)
    }

    fn oku(s: &str) -> Result<Ayar, String> { /* anahtar anahtar ayrıştır */ }
}

Okuyucu her anahtarı türüne göre çevirmeli ve bilinmeyen anahtarda anlaşılır bir hata vermelidir.

Uygulama Ayar gidiş dönüş

Yukarıdaki Ayar türü için json ve oku metotlarını yaz (oku: süslü parantezleri at, virgülden böl, split_once(':'), anahtara göre parse). Ayar { port: 8080, hata_ayikla: false } için JSON'u yazdır, sonra onu geri okuyup {:?} ile yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
#[derive(Debug, PartialEq)]
struct Ayar {
    port: u16,
    hata_ayikla: bool,
}

impl Ayar {
    fn json(&self) -> String {
        format!("{{\"port\":{},\"hata_ayikla\":{}}}", self.port, self.hata_ayikla)
    }

    fn oku(s: &str) -> Result<Ayar, String> {
        let mut port = None;
        let mut hata_ayikla = None;
        for cift in s.trim().trim_start_matches('{').trim_end_matches('}').split(',') {
            let (a, d) = cift.split_once(':').ok_or("geçersiz çift")?;
            let deger = d.trim();
            match a.trim().trim_matches('"') {
                "port" => port = Some(deger.parse().map_err(|_| "geçersiz port")?),
                "hata_ayikla" => hata_ayikla = Some(deger.parse().map_err(|_| "geçersiz bool")?),
                k => return Err(format!("bilinmeyen anahtar: {k}")),
            }
        }
        Ok(Ayar {
            port: port.ok_or("port eksik")?,
            hata_ayikla: hata_ayikla.ok_or("hata_ayikla eksik")?,
        })
    }
}

fn main() {
    let a = Ayar { port: 8080, hata_ayikla: false };
    let metin = a.json();
    println!("{}", metin);
    println!("{:?}", Ayar::oku(&metin).unwrap());
}

Beklenen çıktı

{"port":8080,"hata_ayikla":false}
Ayar { port: 8080, hata_ayikla: false }

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Bir yapılandırmayı yazıp geri okuduğunda aynı değeri almak (round-trip) neden önemli bir testtir?

  • Yazma ve okuma kodlarının birbiriyle uyumlu olduğunu kanıtlar Doğru cevap
  • Performansı ölçer
  • Gerekli değildir
  • Dosya boyutunu küçültür

Açıklama: Elle yazılmış serileştirmede özellikle değerlidir; derive kullanırken bile rename gibi özniteliklerin doğru çalıştığını gösterir.

2 Mantıksal değeri oku

Soru
"hata_ayikla" => hata_ayikla = deger.____().map_err(|_| "geçersiz bool")?,
Cevap
"hata_ayikla" => hata_ayikla = deger.parse().map_err(|_| "geçersiz bool")?,

Açıklama: bool da FromStr uygular: "true"/"false" parse edilir.

3 Grubun özeti

Kavram Anlamı
to_string Yazma
from_str Okuma
rename_all Ad kuralı
skip_serializing_if Boşu atla

Orta seviye bölümündeki tüm dersler