您可以在没有定制Deserialize
实现的情况下做到这一点,但这将需要创建一些额外的类型来处理您的模式中存在的各种备选方案.
因为我们不能直接让Animal
为您的模式实现Deserialize
,所以我们可以创建另一个表示该模式的类型,然后转换为Animal
.#[serde(from = "OtherType")]
将允许我们告诉serde"反序列化OtherType
,然后将其转换为这种类型."
#[derive(Deserialize, Debug)]
#[serde(from = "AnimalRepr")]
enum Animal {
Cat(Option<String>),
Dog(String),
Bird,
}
那么AnimalRepr
是什么样子的呢?它要么是一张 map ,要么是一根线.我们可以使用未标记的枚举来表示这一点.
#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum AnimalRepr {
Animal(AnimalType),
BareAnimalType(BareAnimalType),
}
所以现在AnimalType
将处理 map ,BareAnimalType
将处理字符串.
#[derive(Deserialize, Debug)]
enum BareAnimalType {
Cat,
Bird,
}
#[derive(Deserialize, Debug)]
enum AnimalType {
Cat(String),
Dog(String),
}
现在我们只需要一种将AnimalRepr
转换为Animal
的方法.我们可以通过将BareAnimalType
和AnimalType
都转换为Animal
来拆分这种转换,并在转换AnimalRepr
时委托进行该转换.
impl From<BareAnimalType> for Animal {
fn from(value: BareAnimalType) -> Self {
match value {
BareAnimalType::Cat => Self::Cat(None),
BareAnimalType::Bird => Self::Bird,
}
}
}
impl From<AnimalType> for Animal {
fn from(value: AnimalType) -> Self {
match value {
AnimalType::Cat(n) => Self::Cat(Some(n)),
AnimalType::Dog(n) => Self::Dog(n),
}
}
}
impl From<AnimalRepr> for Animal {
fn from(value: AnimalRepr) -> Self {
match value {
AnimalRepr::Animal(v) => v.into(),
AnimalRepr::BareAnimalType(v) => v.into(),
}
}
}
把所有这些放在一起,我们得到:
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Debug)]
enum BareAnimalType {
Cat,
Bird,
}
impl From<BareAnimalType> for Animal {
fn from(value: BareAnimalType) -> Self {
match value {
BareAnimalType::Cat => Self::Cat(None),
BareAnimalType::Bird => Self::Bird,
}
}
}
#[derive(Deserialize, Debug)]
enum AnimalType {
Cat(String),
Dog(String),
}
impl From<AnimalType> for Animal {
fn from(value: AnimalType) -> Self {
match value {
AnimalType::Cat(n) => Self::Cat(Some(n)),
AnimalType::Dog(n) => Self::Dog(n),
}
}
}
#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum AnimalRepr {
Animal(AnimalType),
BareAnimalType(BareAnimalType),
}
impl From<AnimalRepr> for Animal {
fn from(value: AnimalRepr) -> Self {
match value {
AnimalRepr::Animal(v) => v.into(),
AnimalRepr::BareAnimalType(v) => v.into(),
}
}
}
#[derive(Deserialize, Debug)]
#[serde(from = "AnimalRepr")]
enum Animal {
Cat(Option<String>),
Dog(String),
Bird,
}
fn main() {
let json_animals = r#"
[
{"Cat": "Meow"},
"Cat",
{"Dog": "Bark"},
"Bird"
]"#;
println!("{:?}", serde_json::from_str::<Vec<Animal>>(json_animals).unwrap());
}
其输出:
[Cat(Some("Meow")), Cat(None), Dog("Bark"), Bird]
(Playground)