Skip to content

Error Deserializing Struct With flatten-ed Tagged Enum #278

@nlordell

Description

@nlordell

Version

Tested on both v1.1.6 and master branch.

Briefly describe the bug.

Deserializing a struct with a flattened tagged enum field does not seem to work.

Include a complete program demonstrating a problem.

Code:
#![allow(dead_code)]

use serde::de::DeserializeOwned;
use std::fmt::Debug;

mod tagged_enum {
    use serde::Deserialize;

    #[derive(Debug, Deserialize)]
    pub struct Record {
        common: u64,
        #[serde(flatten)]
        kind: Kind,
    }

    #[derive(Debug, Deserialize)]
    #[serde(tag = "kind", content = "parameter", rename_all = "lowercase")]
    enum Kind {
        Foo(u64),
        Bar(bool),
    }
}

mod flattened_struct {
    use serde::Deserialize;

    #[derive(Debug, Deserialize)]
    pub struct Record {
        common: u64,
        #[serde(flatten)]
        inner: Inner,
    }

    #[derive(Debug, Deserialize)]
    struct Inner {
        kind: Kind,
        parameter: Value,
    }

    #[derive(Debug, Deserialize)]
    #[serde(rename_all = "lowercase")]
    enum Kind {
        Foo,
        Bar,
    }

    #[derive(Debug, Deserialize)]
    #[serde(untagged)]
    enum Value {
        Num(u64),
        Bool(bool),
    }
}

const CSV: &[u8] = b"\
common,kind,parameter
1,foo,42
2,bar,true";

fn dbg_records<T>()
where
    T: Debug + DeserializeOwned,
{
    let mut reader = csv::Reader::from_reader(CSV);
    for record in reader.deserialize::<T>() {
        println!("{:#?}", record);
    }
}

fn main() {
    dbg_records::<tagged_enum::Record>(); // Error!
    dbg_records::<flattened_struct::Record>(); // OK.
}

(Playground link).

What is the observed behavior of the code above?

Fails to deserialize with invalid type: byte array, expected "kind", "parameter", or other ignored fields error:
Err(
    Error(
        Deserialize {
            pos: Some(
                Position {
                    byte: 22,
                    line: 2,
                    record: 1,
                },
            ),
            err: DeserializeError {
                field: None,
                kind: Message(
                    "invalid type: byte array, expected \"kind\", \"parameter\", or other ignored fields",
                ),
            },
        },
    ),
)
Err(
    Error(
        Deserialize {
            pos: Some(
                Position {
                    byte: 31,
                    line: 3,
                    record: 2,
                },
            ),
            err: DeserializeError {
                field: None,
                kind: Message(
                    "invalid type: byte array, expected \"kind\", \"parameter\", or other ignored fields",
                ),
            },
        },
    ),
)

What is the expected or desired behavior of the code above?

To correctly deserialize records as they are done in the case of flattened structs (also included in code example).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions