use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
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());
}
We basically need a way to deserialize both "Cat" and {"Cat": "cat_name"} into Animal. I know that writing a custom deserializer works but it will be better to have a cleaner solution.
I tried aliasing & renaming & options & defining CatVariant as a separate enum to include both cases. None of these works because of Error("invalid type: unit variant, expected newtype variant", line: 5, column: 12)
You can do this without a custom
Deserializeimplementation, but it will require creating a few extra types to handle the various alternatives present in your schema.Since we can't directly make
AnimalimplementDeserializefor your schema, we can create another type that represents that schema and then convert toAnimal.#[serde(from = "OtherType")]will allow us to tell serde "deserializeOtherTypeand then convert it to this type."So what does
AnimalReprlook like? Well, it's either a map or a string. We can used an untagged enum to represent that.So now
AnimalTypewill handle the maps andBareAnimalTypewill handle the strings.Now we just need a way to convert
AnimalReprtoAnimal. We can break this conversion apart by having bothBareAnimalTypeandAnimalTypeconvertible toAnimal, and delegating to that conversion when convertingAnimalRepr.Putting it all together, we get:
Which outputs:
(Playground)