CodeBlanks Logo Icon CodeBlanks

JSON config okuyucu

serde ile config dosyası okuyan bir CLI yazarsın.

Bitirme görevi: config okuyucu

Son görev, gerçek uygulamalardaki tipik bir akışı kurar: yapılandırmayı JSON metninden oku, komut satırı argümanlarıyla ez, hataları anlaşılır mesajlarla bildir. Gerçek projede bunun karşılığı serde_json + clap + anyhow'dur:

#[derive(Deserialize)]
struct Ayar { ad: String, port: u16, hata_ayikla: bool }

let mut ayar: Ayar = serde_json::from_str(&metin).context("ayar okunamadı")?;
if let Some(p) = cli.port { ayar.port = p; }

Alıştırmada okuyucuyu ve ezme mantığını standart kütüphaneyle yazacaksın.

Okuma ve ezme

Okuyucu her anahtarı türüne göre çevirir ve hatayı bağlamıyla döndürür; ezme adımı yalnızca verilen argümanları uygular:

fn oku(json: &str) -> Result<Ayar, String> {
    // anahtar anahtar ayrıştır, port için:
    // deger.parse().map_err(|_| format!("port geçersiz: {deger}"))?
}

fn ez(ayar: &mut Ayar, args: &[&str]) -> Result<(), String> {
    if let Some(i) = args.iter().position(|a| *a == "--port") {
        let s = args.get(i + 1).ok_or("--port değeri eksik")?;
        ayar.port = s.parse().map_err(|_| format!("port geçersiz: {s}"))?;
    }
    Ok(())
}

Uygulama Config okuyucu

Ayar { ad: String, port: u16, hata_ayikla: bool } için oku ve ez fonksiyonlarını yaz. {"ad":"blog","port":3000,"hata_ayikla":false} metnini oku, ["--port", "8080"] ile ez ve ad port hata_ayikla değerlerini yazdır. Ardından "port":"abc" içeren bir metni oku ve hatayı hata: ... olarak yazdır.

Başlangıç kodu

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

Örnek çözüm

main.rs
struct Ayar {
    ad: String,
    port: u16,
    hata_ayikla: bool,
}

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

fn ez(ayar: &mut Ayar, args: &[&str]) -> Result<(), String> {
    if let Some(i) = args.iter().position(|a| *a == "--port") {
        let s = args.get(i + 1).ok_or("--port değeri eksik")?;
        ayar.port = s.parse().map_err(|_| format!("port geçersiz: {s}"))?;
    }
    Ok(())
}

fn main() {
    let mut a = oku(r#"{"ad":"blog","port":3000,"hata_ayikla":false}"#).unwrap();
    ez(&mut a, &["--port", "8080"]).unwrap();
    println!("{} {} {}", a.ad, a.port, a.hata_ayikla);
    match oku(r#"{"ad":"blog","port":"abc"}"#) {
        Ok(_) => println!("tamam"),
        Err(e) => println!("hata: {}", e),
    }
}

Beklenen çıktı

blog 8080 false
hata: port geçersiz: abc

Soru ve cevaplar

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

1 Komut satırı değerinin dosyadakini ezmesi neden yaygın bir kuraldır?

  • Daha hızlıdır
  • Zorunlu değildir
  • Geçici değişiklikler için dosyayı düzenlemek gerekmez Doğru cevap
  • Dosya okunamaz

Açıklama: Öncelik sırası genellikle: argüman > ortam değişkeni > dosya > varsayılan.

2 Ayarı değiştir

Soru
fn ez(ayar: ____, args: &[&str]) -> Result<(), String>
Cevap
fn ez(ayar: &mut Ayar, args: &[&str]) -> Result<(), String>

Açıklama: Ayarı yerinde değiştirmek için &mut gerekir.

3 Girdi ve sonuç

Kavram Anlamı
port 3000 + --port 8080 port 8080
port 3000 (argüman yok) port 3000
"port":"abc" port geçersiz: abc
--port (değersiz) --port değeri eksik

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