【问题标题】:Is there a way to "flatten" enums for (de)serialization in Rust?有没有办法在 Rust 中“扁平化”枚举以进行(反)序列化?
【发布时间】:2019-10-23 23:37:34
【问题描述】:

我有一个由其他枚举组成的枚举,类似于以下内容(为简洁起见,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 稳定之外,我对我的项目没有其他限制,并且我愿意接受任何有用的 crate 建议。

【问题讨论】:

  • 我认为没有任何开箱即用的方法。您可以尝试手动实现反序列化和序列化,如示例serde.rs/custom-serialization.html
  • @Stargateur 问题中已经有关于OP想要什么的例子。具体来说,如果输入是字符串X1,输出应该是Main::A (SubA::X1),如果输入是Y3,输出应该是Main::B (SubB::Y3)...
  • 我不确定serde 是否开箱即用地实现了这一点,因为当您有一个枚举在不同变体中保存相同类型时似乎很难做到(即enum Main{A(SubA), B(SubA)}。应该@ 987654335@ 然后被反序列化为?(如果SubASubB 都包含变体X1,则会出现类似问题。)

标签: enums rust serde


【解决方案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);
}

【讨论】:

    猜你喜欢
    • 2023-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多