I'm trying to parse some JSON with Serde that has a custom enum with an odd format. I've been reading lots on custom deserializers but can't wrap my head around how I'd implement this. Maybe if someone showed me, I could actually start to understand the more generic case. The JSON I need to parse looks like:
{"upgrade": true} // perform a generic upgrade
{"upgrade": "force"} // Generic upgrade + force, note String vs. bool
{"upgrade": "confirm"} // Confirm a previous upgrade.
I suppose I could also add support for {"upgrade": false} as a no-op for consistency, though it's never used. I don't necessarily care that {"upgrade": true} deserializes to a bool--an enum member which I can match against is perfectly fine. I really don't want {"upgrade": "true"}.
Here's my code, using Rust nightly:
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
use std::io;
extern crate serde;
extern crate serde_json;
#[derive(Deserialize, Debug)]
enum UpgradeField {
True,
Force,
Confirm
}
#[derive(Deserialize, Debug)]
struct Data {
upgrade: UpgradeField,
}
fn main() {
let mut input = String::new();
io::stdin().read_line(&mut input)
.expect("Failed to read input");
let data: Data = serde_json::from_str(&input)
.expect("Failed to parse input");
println!("{:?}", data);
}
Actually, I'm not sure why typing {"upgrade": "force"} or {"upgrade": "Force"} causes a panic with:
thread '' panicked at 'Failed to parse input: Syntax("expected value", 1, 13)', ../src/libcore/result.rs:785
So how do I go about getting any of these values to parse, not to mention true vs. "force"/"confirm"? I assumed the values would match on the enum value name, or maybe lower-cased. But that doesn't appear to happen.
This is great, thanks! I have a number of questions about this code, but they're slowly going away as I read through the book.
But here's something I don't get. Not that this issue exists in my project, but say I wanted to suddenly deserialize UpgradeField to XML. Or say I have a crate containing datatypes for a generic API but no serialization/deserialization logic, and maybe I want to implement the deserialization logic in another crate. How would I go about offering multiple data formats, or is that not supported? Or do both formats have to be side-by-side in the same implementation? I was perpetually looking for a JSON-specific way to implement deserialization when it seems I should have been looking at the generic Deserializer.
I am not sure about xml support. There is serde_xml but it looks a bit limited. So, you might need to implement your own custom generic Serializer/Deserializer which is not trivial but there are some examples in serde documentation.
How should the xml look like for the Data struct above?