gpt4 book ai didi

rust - 如何使用可选的内部标签反序列化枚举?

转载 作者:行者123 更新时间:2023-12-03 11:27:39 24 4
gpt4 key购买 nike

我使用Serde反序列化以YAML编写的自定义配置文件。该文件可以包含各种代表我作为内部标记的枚举的定义:

OfKindFoo:
kind: Foo
bar: bar;
baz: baz;

OfKindQux:
kind: Qux
quux: qux;

我用Rust这样表示它:

#[derive(Deserialize)]
#[serde(tag = "kind")]
enum Definition {
Foo(Foo),
Qux(Qux),
}

#[derive(Deserialize)]
struct Foo {
bar: String,
baz: String,
}

#[derive(Deserialize)]
struct Qux {
quux: String,
}

我希望用户能够完全省略 kind字段,并且在省略该字段时,Serde应该默认将其反序列化为 Foo

我开始在 Deserialize上实现 Definition。我正在尝试将其反序列化为 map ,并寻找 kind键,并根据此键以及是否存在返回相应的枚举变量。

我需要以某种方式分别将其他映射字段的反序列化“转发”到 Foo::deserializeBar::deserializefn deserialize只接受一个参数 Deserializer。是否有办法将 map “转换”为解串器,或获得在该特定 map 上“启动”的解串器?

我无法使用 #[serde(other)] ,因为它会为缺少的标签返回 Err。即使没有,文档也指出 other只能应用于“单元变量”,即不包含任何数据的变量。

最佳答案

您可以将主要枚举标记为untagged,然后将标签添加到确实具有标签的子结构中(此功能is not documented,但是是故意添加的,因此可能会保留)。但是,没有标签的变体应该在其他变量之后声明,因为serde会尝试使用#[serde(untagged)]按声明的顺序反序列化这些变体。还要注意,如果在您的实际代码中,变量和结构具有不同的名称,或者您使用的是#[serde(rename)],则结构的名称对于(反)序列化至关重要,而不是变量名称。所有适用于您的示例的内容:

#[derive(Deserialize)]
#[serde(untagged)]
enum Definition {
Qux(Qux),
Foo(Foo), // variant that doesn't have a tag is the last one
}

#[derive(Deserialize)]
struct Foo {
bar: String,
baz: String,
}

#[derive(Deserialize)]
#[serde(tag = "kind")]
// if you want the tag to be "qux" instead of "Qux", do
// #[serde(rename = "qux")]
// here (or add `, rename = "qux"` to the previous serde attribute)
struct Qux {
quux: String,
}

关于rust - 如何使用可选的内部标签反序列化枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61216723/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com