在Rust中是否有一种“铺平”枚举类型以进行序列化和反序列化的方法?

7
我有一个枚举类型,它由其他枚举类型组成,类似于以下内容(为简洁起见省略了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支持在新类型样式结构上使用#[serde(transparent)]属性,这样就可以实现我想要的效果。但是,它似乎只能在结构体或枚举层面上工作,而不能在枚举变体层面上工作。是否有一种方法可以自动获得我所需的行为?我可以确保任何包含子枚举的变量名称都不会重叠。除了想保持Rust 2018稳定之外,我的项目没有其他限制,我愿意接受任何可以帮助我完成目标的建议。

1
我认为没有现成的方法可以做到这一点。您可以尝试手动实现反序列化和序列化,就像示例中所述 https://serde.rs/custom-serialization.html - dotPoozer
@Stargateur,问题中已经有了OP想要的示例。具体来说,如果输入是字符串X1,则输出应为Main::A (SubA::X1),如果输入是Y3,则输出应为Main::B (SubB::Y3)... - Jmb
1
我不确定serde是否可以直接实现这个功能,因为当你有一个枚举类型在不同的变量中持有相同的类型时(例如enum Main{A(SubA), B(SubA)}),这似乎很难做到。那么X1应该反序列化成什么呢?(如果SubASubB都包含一个变量X1,则会出现类似的问题。) - phimuemue
1个回答

12

如果您将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);
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接