如何解决如何从字符串或数字反序列化无字段枚举?
是否有一种简洁的方法可以根据名称或判别值反序列化无字段枚举的变体?例如给定这个枚举——
enum Foo {
A = 1,B = 2,C = 3,}
——我想要这些字符串或数字中的任何一个来表示它:
{
"example-a": "a",// Foo::A
"example-b": "b",// Foo::B
"example-c": "c",// Foo::C
"example-1": 1,// Foo::A
"example-2": 2,// Foo::B
"example-3": 3,// Foo::C
}
我已经看到派生 Deserialize
可以容纳前一组,Deserialize_repr
可以容纳后者,但我不确定如何同时容纳这两个组。
我预计可能存在像 #[serde(alias = …)]
这样的速记来涵盖这种情况。
解决方法
没有直接支持此功能的内置快捷方式。您必须手动实现 Deserialize
。这既不琐碎也不复杂:
impl<'de> serde::Deserialize<'de> for Foo {
fn deserialize<D>(deserializer: D) -> Result<Self,D::Error>
where
D: serde::Deserializer<'de>
{
struct FooVisitor;
impl<'de> serde::de::Visitor<'de> for FooVisitor {
type Value = Foo;
fn expecting(&self,formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter,"an integer or string representing a Foo")
}
fn visit_str<E: serde::de::Error>(self,s: &str) -> Result<Foo,E> {
Ok(match s {
"a" => Foo::A,"b" => Foo::B,"c" => Foo::C,_ => return Err(E::invalid_value(serde::de::Unexpected::Str(s),&self)),})
}
fn visit_u64<E: serde::de::Error>(self,n: u64) -> Result<Foo,E> {
Ok(match n {
1 => Foo::A,2 => Foo::B,3 => Foo::C,_ => return Err(E::invalid_value(serde::de::Unexpected::Unsigned(n),})
}
}
deserializer.deserialize_any(FooVisitor)
}
}
请注意,使用 deserialize_any
意味着我们依赖于自我描述的数据格式;即,反序列化器知道数据是字符串还是整数,并将相应地调用正确的 visit_
方法。 Serde 还支持非自描述格式;但是,您将无法在此 Deserialize
实现中使用它们。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。