Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Error when deserializing sequence of untagged enum #361

Open
kafkiansky opened this issue Mar 16, 2023 · 2 comments
Open

Error when deserializing sequence of untagged enum #361

kafkiansky opened this issue Mar 16, 2023 · 2 comments

Comments

@kafkiansky
Copy link

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?

@mexus
Copy link

mexus commented Jun 29, 2023

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 #342

gp27 added a commit to gp27/halleypack-rust that referenced this issue Dec 3, 2023
Temporary fix while waiting for this issue to be resolved: dtolnay/serde-yaml#361
Unfortunately it makes the yaml quite unreadable
@sambonbonne
Copy link

I confirm I have the same bug in 0.9 but not in 0.8.

# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants