I'm writing for a program that hooks into a web service which sends back JSON.
When a certain property isn't there it provides a empty object, with all its fields as empty strings instead of excluding the value. When the property exists, some of the properties are u64
. How can I have it so Serde handles this case?
Rust Structs
#[derive(Clone, Debug, Deserialize)]
struct WebResponse {
foo: Vec<Foo>,
}
#[derive(Clone, Debug, Deserialize)]
struct Foo {
points: Points,
}
#[derive(Clone, Debug, Deserialize)]
struct Points {
x: u64,
y: u64,
name: String,
}
Example JSON
{
"foo":[
{
"points":{
"x":"",
"y":"",
"name":""
}
},
{
"points":{
"x":78,
"y":92,
"name":"bar"
}
}
]
}
Serde supports an interesting selection of attributes that can be used to customize the serialization or deserialization for a type while still using the derived implementation for the most part.
In your case, you need to be able to decode a field that can be specified as one of multiple types, and you don't need information from other fields to decide how to decode the problematic fields. The
#[serde(deserialize_with="$path")]
annotation is well suited to solve your problem.We need to define a function that will decode either an empty string or an integer value into an
u64
. We can use the same function for both fields, since we need the same behavior. This function will use a customVisitor
to be able to handle both strings and integers. It's a bit long, but it makes you appreciate all the work that Serde is doing for you!Cargo.toml
: