Reading JSON
- Rust course
- Intermediate
- Lesson 108/115
- 6 min
Read a list of posts with serde_json.
Reading the data
In a real project posts are read from a JSON array in a single line:
let metin = fs::read_to_string("yazilar.json")?;
let yazilar: Vec<Yazi> = serde_json::from_str(&metin)?;Since there are no external crates in the exercise, we'll use a simpler record format: one record per line, fields separated by |, tags by commas:
1|Rust ile başlangıç|ece|rust,giriş|true
2|Sahiplik|can|rust|falseParsing a record
The record is split at |; if the number of fields is wrong or a field can't be converted, None is returned. A slice pattern names the five fields in one step:
fn kayittan(s: &str) -> Option<Yazi> {
let alanlar: Vec<&str> = s.split('|').collect();
let [id, konu, yazar, etiket, yayinda] = alanlar[..] else {
return None;
};
Some(Yazi {
id: id.parse().ok()?,
konu: konu.to_string(),
yazar: yazar.to_string(),
etiketler: etiket.split(',').map(String::from).collect(),
yayinda: yayinda.parse().ok()?,
})
}Practice Read the records
Write the kayittan function above. Read three lines of data (two valid, the third 3|bozuk kayıt) with lines() and filter_map; print it as 2 kayıt: topic1, topic2.
Starter code
#[derive(Debug, Clone)]
struct Yazi {
id: u32,
konu: String,
yazar: String,
etiketler: Vec<String>,
yayinda: bool,
}
fn main() {
// buraya yaz
}Sample solution
#[derive(Debug, Clone)]
struct Yazi {
id: u32,
konu: String,
yazar: String,
etiketler: Vec<String>,
yayinda: bool,
}
fn kayittan(s: &str) -> Option<Yazi> {
let alanlar: Vec<&str> = s.split('|').collect();
let [id, konu, yazar, etiket, yayinda] = alanlar[..] else {
return None;
};
Some(Yazi {
id: id.parse().ok()?,
konu: konu.to_string(),
yazar: yazar.to_string(),
etiketler: etiket.split(',').map(String::from).collect(),
yayinda: yayinda.parse().ok()?,
})
}
fn main() {
let veri = "1|Rust ile başlangıç|ece|rust,giriş|true\n2|Sahiplik|can|rust|false\n3|bozuk kayıt";
let yazilar: Vec<Yazi> = veri.lines().filter_map(kayittan).collect();
let konular: Vec<&str> = yazilar.iter().map(|y| y.konu.as_str()).collect();
println!("{} kayıt: {}", yazilar.len(), konular.join(", "));
}Expected output
2 kayıt: Rust ile başlangıç, Sahiplik
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What is the risk of silently skipping a broken record?
- The program slows down
- Compile error
- There's no risk
- Data loss goes unnoticed; at least the count should be reported Correct answer
Explanation: In this lesson we skip broken ones; in the next lesson we'll report each error with its number.
2 Collect the valid ones
let yazilar: Vec<Yazi> = veri.lines().____(kayittan).collect();
let yazilar: Vec<Yazi> = veri.lines().filter_map(kayittan).collect();
Explanation: filter_map drops the None results and collects what's inside Some.
3 Record and result
| Term | Meaning |
|---|---|
1|Rust|ece|rust|true |
Some(Yazi) |
3|bozuk kayıt |
None (fields missing) |
x|a|b|c|true |
None (invalid id) |
1|a|b|c|evet |
None (invalid bool) |