有没有一种方法可以使Rust中的(反)序列化枚举“变平”?

时间:2019-10-23 23:37:34

标签: enums rust serde

我有一个由其他枚举组成的枚举,类似于以下内容(为简洁起见,serde的派生和注释被省略):

enum Main {
    A(SubA),
    B(SubB),
}

enum SubA { X1, X2, X3 }
enum SubB { Y1, Y2, Y3 }

我很希望能够使用serde来反序列化诸如“ X1”或“ Y3”之类的字符串,并分别自动返回Main::A(SubA::X1)Main::B(SubB::Y3)

我了解到serde在newtype样式结构上支持#[serde(transparent)]属性,这可以满足我的要求。但是,它似乎仅在结构或枚举级别起作用,而不在枚举变量级别起作用。有没有办法我可以自动获得想要的行为?我可以确保所包含的任何子枚举中的任何变体名称都不会重叠。

除了希望保持Rust 2018稳定之外,我对我的项目没有其他限制,并且愿意接受任何有帮助的板条箱建议。

1 个答案:

答案 0 :(得分:1)

如果将serde(untagged)放在外部枚举上,而在内部枚举上没有什么特殊之处,它几乎是开箱即用的:

use serde_derive::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(untagged)]
enum Main {
    A(SubA),
    B(SubB),
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
enum SubA { X1, X2, X3 }

#[derive(Debug, Deserialize, Serialize, PartialEq)]
enum SubB { Y1, Y2, Y3 }

fn main() {
    let x1 = Main::A(SubA::X1);
    let y2 = Main::B(SubB::Y2);

    assert_eq!(serde_json::to_string(&x1).unwrap(), "\"X1\"");
    assert_eq!(serde_json::to_string(&y2).unwrap(), "\"Y2\"");

    assert_eq!(serde_json::de::from_str::<Main>("\"X1\"").unwrap(), x1);
    assert_eq!(serde_json::de::from_str::<Main>("\"Y2\"").unwrap(), y2);
}