serde-yaml
serde-yaml copied to clipboard
Error when deserializing sequence of untagged enum
On serde_yaml version 0.8 this code works fine:
use serde::{Deserialize};
use serde_yaml::{from_str};
#[derive(Debug, Deserialize)]
pub enum When {
Conditions(Vec<When>),
#[serde(rename = "active")]
Active {
until: i32,
},
#[serde(rename = "starts_with")]
StartsWith {
name: String,
}
}
pub type Conditions = Vec<When>;
#[derive(Debug, Deserialize)]
pub struct Job {
when: Conditions,
}
fn main() {
let yaml = r#"
when:
- active: {until: 300}
- starts_with: {name: "internal_*"}
"#;
let job: Job = from_str(yaml).unwrap();
println!("{:#?}", job.when);
}
But on 0.9 raise an error:
"when[0]: invalid type: map, expected a YAML tag starting with '!'", line: 3, column: 14
Is this expected behavior or is it a bug?
This is probably what you want: https://docs.rs/serde_yaml/0.9.22/serde_yaml/with/singleton_map_recursive/index.html
I guess we need to apply a serde_yaml::with::singleton_map deserializer to the When struct, and in order to do so we can make a newtype for that purpose (the #[serde(with = ...)] won't work properly when applied to Vec<When>):
use serde::Deserialize;
use serde_yaml::from_str;
#[derive(Debug, Deserialize)]
pub enum When {
Conditions(Vec<When>),
#[serde(rename = "active")]
Active {
until: i32,
},
#[serde(rename = "starts_with")]
StartsWith {
name: String,
},
}
pub type Conditions = Vec<When>;
#[derive(Debug, Deserialize)]
pub struct Job {
#[serde(with = "serde_yaml::with::singleton_map_recursive")]
when: Conditions,
}
fn main() {
let yaml = r#"
when:
- active: {until: 300}
- starts_with: {name: "internal_*"}
"#;
let job: Job = from_str(yaml).unwrap();
println!("{:#?}", job.when);
}
There's also another custom (de)serializer https://docs.rs/serde_yaml/0.9.22/serde_yaml/with/singleton_map/index.html , but it would be more tricky to install (you're going to need a newtype or something, since it won't make any effect on Vec<T>).
Also see discussion at https://github.com/dtolnay/serde-yaml/issues/342
I confirm I have the same bug in 0.9 but not in 0.8.