Reputation: 57
I have json documents, that may contain objects which have keys that refer to empty objects, like this
{
"mylist": {
"foo": {},
"bar": {}
}
}
I would like to deserialize them to a Vec of Strings (and serialize it back to the format above later)
pub struct MyStruct {
#[serde(skip_serializing_if = "Option::is_none")]
pub my_list: Option<Vec<String>>; // should contain "foo", "bar"
}
How can I do that with serde?
Upvotes: 2
Views: 1190
Reputation: 42746
You need to write your own deserializing method, and use deserialize_with
or implement it directly for your type:
use serde::Deserialize; // 1.0.127
use serde::Deserializer;
use serde_json;
use std::collections::HashMap; // 1.0.66
#[derive(Deserialize, Debug)]
pub struct MyStruct {
#[serde(deserialize_with = "deserialize_as_vec", alias = "mylist")]
pub my_list: Vec<String>,
}
#[derive(Deserialize)]
struct DesHelper {}
fn deserialize_as_vec<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where
D: Deserializer<'de>,
{
let data: HashMap<String, DesHelper> = HashMap::<String, DesHelper>::deserialize(deserializer)?;
Ok(data.keys().cloned().collect())
}
fn main() {
let example = r#"
{
"mylist": {
"foo": {},
"bar": {}
}
}"#;
let deserialized: MyStruct = serde_json::from_str(&example).unwrap();
println!("{:?}", &deserialized);
}
Results:
MyStruct { my_list: ["foo", "bar"] }
Notice the use of the helper struct for the empty parts of them. Code is pretty straight forward, you basically deserialize a map and then just take the keys that is what you need.
Upvotes: 3