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.

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

No branches or pull requests

3 participants