使用 serde 以字符串形式获取枚举变量的名称

Men*_*ndy 13 rust serde serde-json

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

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

那么我怎样才能获得变体的 serde 名称呢?就像是

serde::key_name(SomeEnum::WithoutValue) // should be `withoutValue`
serde::key_name(SomeEnum::WithValue)    // should be `withValue`
Run Code Online (Sandbox Code Playgroud)

serde_json对于没有值的变体,我可以使用 , 进行黑客攻击:

serde_json::to_string(SomeEnum::WithoutValue).unwrap(); // yields `"withoutValue"` with quotation marks
Run Code Online (Sandbox Code Playgroud)

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

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

serde_json::to_string(SomeEnum::WithValue(0)).unwrap(); // yields `"{\"second\":0}"
Run Code Online (Sandbox Code Playgroud)

有没有一种干净的方法来实现这一目标?我找不到 serde API 来获取字符串形式的键名。

jon*_*sbb 7

提取变体信息的一种稳定但有点样板的方法是实现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");
Run Code Online (Sandbox Code Playgroud)

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