In the yaml files below:
// 1. book yaml
kind: book
title: Someone's life
publisher: someone
published_at: 2023-02-24T09:31:00Z+09:00
// 2. movie yaml
kind: movie
title: Someone's life
director: someone else
kind
is key for recognizing that yaml is what for. If kind is book
, this matter have publisher
and published_at
. however, if kind is movie
, this matter doesn't have publisher
but director
.
In my short thought, for parsing it, i have to make general parse struct. ex:
#[derive(Serialize, Deserialize, Debug)]
struct General {
kind: String,
title: String,
}
parse one time using General struct, then get parsed general's kind and re-parse with another struct. ex:
#[derive(Serialize, Deserialize, Debug)]
struct Book {
kind: String,
title: String,
publisher: String,
published_at: String,
}
Above scenario can be works, but i have to parse two time. But, Is this efficient?
You can use serde's tag attribute for this. Playground example
use serde::Deserialize;
use serde_yaml; // 0.8.26
#[derive(Debug, Deserialize)]
#[serde(tag="kind", rename_all="lowercase")]
enum Media {
Book(Book),
Movie(Movie),
}
#[derive(Debug, Deserialize)]
struct Book {
title: String,
publisher: String,
published_at: String,
}
#[derive(Debug, Deserialize)]
struct Movie {
title: String,
director: String,
}
fn main() {
let book: Media = serde_yaml::from_str("kind: book
title: Someone's life
publisher: someone
published_at: 2023-02-24T09:31:00Z+09:00").unwrap();
let movie: Media = serde_yaml::from_str("kind: movie
title: Someone's life
director: someone else").unwrap();
println!("{book:?}");
println!("{movie:?}");
}