Deserializing YAML with a list of String or Map

Hi,

So I'm trying to find a solution to consume the following YAML with a Struct:

entries:
  - alias: xyz
    real_name: abc
  - hjkl

Why do I have a single string mixed with a map? The single string means that both "alias" and "real_name" map entries have the same value.

I can probably handle this scenario using serde_yaml::Value but I wanted to confirm that it cannot be resolve through serde macro that could set a custom micro-parse for it. Something like:

serde_yaml::Deserialize

#[derive(Deserialize)]
struct Entry {
    alias: String,
    real_name: String,
}

#[derive(Deserialize)]
struct YamlFile {
    #[serde(customer_parse("parse_entry"))]
    entries: Vec<Entry>,
}

fn parse_entry(value: &serde_yaml::Value) -> Entry {
    // ...
}

Thank you :slight_smile:

Just to confirm, you want something like YamlFile {entries: vec![Entry {alias: "xyz", real_name: "abc"}, Entry {alias: "hjkl", real_name: "hjkl"}] as a result?

Yes :smiley:

I would do it like this:

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct YamlFile {
    entries: Vec<Entry>,
}

#[derive(Debug)]
struct Entry {
    alias: String,
    real_name: String,
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum EntrySer {
    Same(String),
    Different { alias: String, real_name: String },
}

impl<'de> Deserialize<'de> for Entry {
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        Ok(match EntrySer::deserialize(deserializer)? {
            EntrySer::Same(s) => Entry {
                alias: s.clone(),
                real_name: s,
            },
            EntrySer::Different { alias, real_name } => Entry { alias, real_name },
        })
    }
}

fn main() {
    dbg!(serde_yaml::from_str::<YamlFile>(
        "\
entries:
  - alias: xyz
    real_name: abc
  - hjkl"
    ));
}

The derived Deserialize for EntrySer does the actual parsing of the two cases, and the manual Deserialize for Entry converts that into the desired data structure.

3 Likes

Wow! What a beautiful piece of code. Appreciate the help :smiley:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.