您可以使用未标记的枚举 https://serde.rs/enum-representations.html#untagged为了这。详细信息取决于您具体想要做什么。想法是包装Foo
into a MaybeFoo
, where MaybeFoo
有一个“通用”类型可以反序列化为第二选择。
在下面的示例中,我们使用serde_json::Value https://docs.rs/serde_json/1.0.57/serde_json/enum.Value.html作为虚拟类型,作为其实现Deserialize
是通用的,因为可以反序列化任何有效的 JSON。如果您的源格式不同,您可能需要不同的解串器或实现Deserialize
你自己。
#[derive(serde::Deserialize, serde::Serialize, PartialEq, Debug)]
enum Foo {
A(u64),
B(f32),
C(String),
}
// MaybeFoo is untagged, which also means it "looks" exactly
// like a Foo when serialized/deserialized.
#[derive(serde::Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum MaybeFoo {
Foo(Foo),
Other(serde_json::Value)
}
The MaybeFoo
是一个“未标记”的枚举,Serde 将尝试反序列化MaybeFoo
as a Foo
并且 - 如果失败 - 作为serde_json::Value
它总是会成功(如果源自 JSON)。
fn main() {
// Lets create a Foo and serialize it
let foo = Foo::B(0.0);
let foo_json = serde_json::to_string(&foo).unwrap();
println!("{}", &foo_json);
// Deserialize works as expected
let foo_json = "{\"B\":0.0}";
assert!(serde_json::from_str::<Foo>(&foo_json).unwrap() == foo);
// Deserializing as a `MaybeFoo` works as expected
assert!(serde_json::from_str::<MaybeFoo>(&foo_json).unwrap() == MaybeFoo::Foo(foo));
// Deserializing something else is not a `Foo`!
let foo_json = "{\"Unknown\":0.0}";
let foo = serde_json::from_str::<MaybeFoo>(&foo_json).unwrap();
// Prints "Other(Object({"Unknown": Number(0.0)}))"
println!("{:?}", &foo);
}
您可以使用 serde_json 的 API 来检查未知变体 - 如果它看起来像地图 - 提取标签。如果这是您唯一的兴趣,则第二种变体MaybeFoo
也可以是一个HashMap<String, serde::de::IgnoredAny>
,这将反序列化任何地图,将标签记录为String
并丢弃该值。然而,这假定未知值是标记值。