7

我正在尝试获取枚举变体的名称,因为字符串 serde 期望/创建。例如,假设我有以下枚举:

#[derive(Serialize, Deserialize)]
#[serde(rename_all="camelCase")]
pub enum SomeEnum {
    WithoutValue,
    withValue(i32),
}

然后我怎样才能获得变体的 serde 名称?就像是

serde::key_name(SomeEnum::WithoutValue) // should be `withoutValue`
serde::key_name(SomeEnum::WithValue)    // should be `withValue`

serde_json对于没有值的变体,我可以使用, 我可以做的变体:

serde_json::to_string(SomeEnum::WithoutValue).unwrap(); // yields `"withoutValue"` with quotation marks

这不是最好的解决方案,因为我需要去掉引号,但在技术上可以工作。

更糟糕的是当枚举变体具有值时。它变得更加混乱。

serde_json::to_string(SomeEnum::WithValue(0)).unwrap(); // yields `"{\"second\":0}"

有没有一种干净的方法来实现这一目标?我找不到将密钥名称作为字符串获取的 serde API。

4

2 回答 2

5

提取变体信息的一种稳定但有点样板化的繁重方法是通过实现从函数Serializer中收集变体名称的自定义serialize_*_variant

这是所采取的方法serde_variant。@Mendy 提到此板条箱仅适用于单元变体。这是自述文件中的示例。

use serde_variant::to_variant_name;

#[derive(Serialize)]
enum Foo {
  Var1,
  #[serde(rename = "VAR2")]
  Var2,
}

assert_eq!(to_variant_name(&Foo::Var1).unwrap(), "Var1");
assert_eq!(to_variant_name(&Foo::Var2).unwrap(), "VAR2");

另一个需要提到的缺点是,这只适用于默认的、外部标记的枚举表示。其他表示不使用这些serialize_*_variant功能。

于 2021-04-22T16:33:01.470 回答
0

当 Enum 变体没有值时,它将被序列化为 a String,否则它将被序列化为以变体名称为键的对象。

基本上,您的 Enum 将按如下方式序列化:

#[derive(Serialize)]
struct MyStruct {
  my_field: SomeEnum,
  some_other_field: String,
};

带有变体的 Json 示例withValue

{
  "my_field": {
    "withValue": 2
  },
  "some_other_field": "I like turtles"
}

带有变体的 Json 示例WithoutValue

{
  "my_field": "withoutValue",
  "some_other_field": "Boom goes the dynamite"
}
于 2021-04-22T17:52:20.590 回答