Skip to content

#[serde(untagged)] no longer works correctly in serde versions 1.0.220 and above #583

@rxdiscovery

Description

@rxdiscovery

Hello,

Since I upgraded the serde crate from version 1.0.219 to 1.0.224, the #[serde(untagged)] attribute no longer works.

Here is some code to run the tests :

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(untagged)]
pub enum WrapperStruct {
    Single(ValueStruct),
    Multiple(Vec<ValueStruct>),
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub enum ValueStruct {
    String(String),
    Integer(i64),
    Decimal(f64),
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // ---------------------- JSON
    println!("----------JSON----------");

    // Example 1: a single string value
    let json_single = r#"{"String": "hello"}"#;
    let single: WrapperStruct = serde_json::from_str(json_single)?;
    println!("Single: {:?}", single);

    // Example 2: a single numeric value (integer)
    let json_integer = r#"{"Integer": 42}"#;
    let integer: WrapperStruct = serde_json::from_str(json_integer)?;
    println!("Integer: {:?}", integer);

    // Example 3: multiple values
    let json_multiple = r#"[{"String": "hello"}, {"Integer": 123}, {"Decimal": 45.67}]"#;
    let multiple: WrapperStruct = serde_json::from_str(json_multiple)?;
    println!("Multiple: {:?}", multiple);

    // ---------------------- RON
    println!("----------RON----------");

    // Example 1: a single string value
    let ron_single = r#"String("hello")"#;
    let single: WrapperStruct = ron::from_str(ron_single)?;
    println!("Single: {:?}", single);

    // Example 2: a single integer value
    let ron_integer = r#"Integer(42)"#;
    let integer: WrapperStruct = ron::from_str(ron_integer)?;
    println!("Integer: {:?}", integer);

    // Example 3: multiple values
    let ron_multiple = r#"[String("hello"), Integer(123), Decimal(45.67)]"#;
    let multiple: WrapperStruct = ron::from_str(ron_multiple)?;
    println!("Multiple: {:?}", multiple);

    // Serialization back to RON
    let ron_output = ron::to_string(&multiple)?;
    println!("Serialized to RON: {}", ron_output);

    Ok(())
}

Results :

With serde version 1.0.219 :

[package]
name = "bug_serde"
version = "0.1.0"
edition = "2024"

[dependencies]
ron = "0.11.0"
serde = { version = "=1.0.219", features = ["derive"] }
serde_json = "1.0.132"
----------JSON----------
Single: Single(String("hello"))
Integer: Single(Integer(42))
Multiple: Multiple([String("hello"), Integer(123), Decimal(45.67)])
----------RON----------
Single: Single(String("hello"))
Integer: Single(Integer(42))
Multiple: Multiple([String("hello"), Integer(123), Decimal(45.67)])
Serialized to RON: [String("hello"),Integer(123),Decimal(45.67)]

With serde version 1.0.220 :

[package]
name = "bug_serde"
version = "0.1.0"
edition = "2024"

[dependencies]
ron = "0.11.0"
serde = { version = "1.0.220", features = ["derive"] }
serde_json = "1.0.132"
----------JSON----------
Single: Single(String("hello"))
Integer: Single(Integer(42))
Multiple: Multiple([String("hello"), Integer(123), Decimal(45.67)])
----------RON----------
Error: SpannedError { code: Message("data did not match any variant of untagged enum WrapperStruct"), span: Span { start: Position { line: 1, col: 15 }, end: Position { line: 1, col: 16 } } }

With serde version 1.0.225 :

[package]
name = "bug_serde"
version = "0.1.0"
edition = "2024"

[dependencies]
ron = "0.11.0"
serde = { version = "1.0.225", features = ["derive"] }
serde_json = "1.0.145"
----------JSON----------
Single: Single(String("hello"))
Integer: Single(Integer(42))
Multiple: Multiple([String("hello"), Integer(123), Decimal(45.67)])
----------RON----------
Error: SpannedError { code: Message("data did not match any variant of untagged enum WrapperStruct"), span: Span { start: Position { line: 1, col: 15 }, end: Position { line: 1, col: 16 } } }

So the bug has appeared since version 1.0.220

Now have to pin the old version in Cargo.toml.

serde = { version = "=1.0.219", features = ["derive"] }

Thank you in advance for your help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions