From IRC:
\
is it possible in serde/json to deserialize JSON that is expecting a Vector into a Hashmap with a key that is present in the same JSON struct
\https://pastebin.com/JrssZRkW
Here is one possible approach:
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize)]
pub struct ItemsWrapper {
#[serde(with = "items")]
pub items: HashMap<i64, Items>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Items {
// This is the HashMap key.
id: i64,
info: String,
}
mod items {
use super::Items;
use std::collections::HashMap;
use serde::ser::Serializer;
use serde::de::{Deserialize, Deserializer};
pub fn serialize<S>(map: &HashMap<i64, Items>, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.collect_seq(map.values())
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<HashMap<i64, Items>, D::Error>
where D: Deserializer<'de>
{
let mut map = HashMap::new();
for item in Vec::<Items>::deserialize(deserializer)? {
map.insert(item.id, item);
}
Ok(map)
}
}
fn main() {
let j = r#" {
"items": [
{
"id": 3,
"info": "three"
},
{
"id": 2,
"info": "two"
}
]
} "#;
println!("{:#?}", serde_json::from_str::<ItemsWrapper>(j).unwrap());
}
Shouldn't this be more performant:
pub fn deserialize<'de, D>(deserializer: D) -> Result<HashMap<i64, Items>, D::Error>
where
D: Deserializer<'de>,
{
struct ItemsVisitor;
impl<'de> Visitor<'de> for ItemsVisitor {
type Value = HashMap<i64, Items>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a sequence of items")
}
fn visit_seq<V>(self, mut seq: V) -> Result<HashMap<i64, Items>, V::Error>
where
V: SeqAccess<'de>,
{
let mut map = HashMap::with_capacity(seq.size_hint().unwrap_or(0));
while let Some(item) = seq.next_element::<Items>()? {
map.insert(item.id, item);
}
Ok(map)
}
}
deserializer.deserialize_seq(ItemsVisitor)
}
? My gut feeling tells me it should because this does not allocate a temporary Vec. But cargo bench reports that the difference is negligible (when deserializing arrays of >500 elements), what am I missing?
Most helpful comment
Here is one possible approach: