问题
I have the following YAML:
build:
- step 1
- step 2
- name: step 3
do: something
- name: step 4
get: fetch ...
- name: step 5
put: upload something
And for parsing it I am trying with this
#[derive(Debug, Deserialize, PartialEq)]
struct Config {
build: Option<Vec<Steps>>
}
#[derive(Debug, Deserialize, PartialEq)]
struct Build {
#[serde(flatten)]
item: String,
steps: Steps,
}
#[derive(Debug, Deserialize, PartialEq)]
struct Steps {
name: String,
r#do: Option<String>,
put: Option<String>,
get: Option<String>,
}
But I get this error:
Error parsing configuration file: build[0]: invalid type: string "step 1", expected struct Build
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0ddb0eb8be0888e74b089eb0ebc5daee
I do can parse only:
build:
- step 1
- step 2
Using this:
#[derive(Debug, Deserialize, PartialEq)]
struct Config {
build: Option<Vec<String>>
}
Or:
build:
- name: step 1
do: foo
- name: step 2
do: bar
Using:
#[derive(Debug, Deserialize, PartialEq)]
struct Config {
build: Option<Vec<Steps>>
}
But can't find a way to have both options, any idea about how could this be parsed?
回答1:
Use an enum:
#[derive(Debug, serde::Deserialize, PartialEq)]
struct Build {
build: Vec<Foo>,
}
#[derive(Debug, serde::Deserialize, PartialEq)]
#[serde(untagged)]
enum Foo {
Step(Step),
Bar(String),
}
#[derive(Debug, serde::Deserialize, PartialEq)]
struct Step {
name: String,
#[serde(rename = "do")]
make: Option<String>,
put: Option<String>,
get: Option<String>,
}
fn main() -> Result<(), serde_yaml::Error> {
let input = r#"build:
- step 1
- step 2
- name: step 3
do: something
- name: step 4
get: fetch ...
- name: step 5
put: upload something"#;
let build: Build = serde_yaml::from_str(input)?;
println!("{:#?}", build);
Ok(())
}
来源:https://stackoverflow.com/questions/61793475/how-to-parse-a-yaml-containing-a-simple-list-together-with-a-key-value-list-ass