pub mod serde_vec_of_maps {
use serde::de::DeserializeOwned;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
use std::hash::Hash;
pub fn serialize<K, V, S>(vec: &[HashMap<K, V>], ser: S) -> Result<S::Ok, S::Error>
where
K: Serialize + Eq + Hash,
V: Serialize,
S: Serializer,
{
let nested: Vec<Vec<(&K, &V)>> = vec.iter().map(|m| m.iter().collect()).collect();
nested.serialize(ser)
}
pub fn deserialize<'de, K, V, D>(de: D) -> Result<Vec<HashMap<K, V>>, D::Error>
where
K: DeserializeOwned + Eq + Hash,
V: DeserializeOwned,
D: Deserializer<'de>,
{
let nested: Vec<Vec<(K, V)>> = Vec::deserialize(de)?;
Ok(nested
.into_iter()
.map(|pairs| pairs.into_iter().collect())
.collect())
}
}
pub mod serde_map_set_as_vec {
use serde::de::DeserializeOwned;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::{HashMap, HashSet};
use std::hash::Hash;
pub fn serialize<K, V, S>(map: &HashMap<K, HashSet<V>>, ser: S) -> Result<S::Ok, S::Error>
where
K: Serialize + Eq + Hash,
V: Serialize + Eq + Hash,
S: Serializer,
{
let pairs: Vec<(&K, Vec<&V>)> = map
.iter()
.map(|(k, set)| (k, set.iter().collect()))
.collect();
pairs.serialize(ser)
}
pub fn deserialize<'de, K, V, D>(de: D) -> Result<HashMap<K, HashSet<V>>, D::Error>
where
K: DeserializeOwned + Eq + Hash,
V: DeserializeOwned + Eq + Hash,
D: Deserializer<'de>,
{
let pairs: Vec<(K, Vec<V>)> = Vec::deserialize(de)?;
Ok(pairs
.into_iter()
.map(|(k, vec)| (k, vec.into_iter().collect()))
.collect())
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
#[derive(Serialize, Deserialize, Debug)]
struct VecOfMapsWrapper {
#[serde(with = "serde_vec_of_maps")]
data: Vec<HashMap<String, f64>>,
}
#[derive(Serialize, Deserialize, Debug)]
struct MapSetWrapper {
#[serde(with = "serde_map_set_as_vec")]
data: HashMap<String, HashSet<usize>>,
}
#[test]
fn test_serde_vec_of_maps_round_trip() {
let mut m1: HashMap<String, f64> = HashMap::new();
m1.insert("alpha".into(), 1.0);
m1.insert("beta".into(), 2.5);
let m2: HashMap<String, f64> = HashMap::new();
let mut m3: HashMap<String, f64> = HashMap::new();
m3.insert("gamma".into(), 0.0);
let original = VecOfMapsWrapper {
data: vec![m1.clone(), m2.clone(), m3.clone()],
};
let json = serde_json::to_string(&original).expect("serialisation must succeed");
let recovered: VecOfMapsWrapper =
serde_json::from_str(&json).expect("deserialisation must succeed");
assert_eq!(
recovered.data.len(),
3,
"round-trip must preserve the number of maps"
);
assert!(
recovered.data[1].is_empty(),
"empty map at index 1 must survive round-trip"
);
assert_eq!(
recovered.data[0].get("alpha").copied(),
Some(1.0),
"alpha key must survive round-trip"
);
assert_eq!(
recovered.data[2].get("gamma").copied(),
Some(0.0),
"gamma=0.0 must survive round-trip"
);
}
#[test]
fn test_serde_map_set_as_vec_round_trip() {
let mut original_data: HashMap<String, HashSet<usize>> = HashMap::new();
original_data.insert("key_a".into(), [1, 2, 3].iter().copied().collect());
original_data.insert("key_b".into(), HashSet::new());
original_data.insert("key_c".into(), [42].iter().copied().collect());
let wrapper = MapSetWrapper {
data: original_data.clone(),
};
let json = serde_json::to_string(&wrapper).expect("serialisation must succeed");
let recovered: MapSetWrapper =
serde_json::from_str(&json).expect("deserialisation must succeed");
assert_eq!(
recovered.data.len(),
3,
"round-trip must preserve key count"
);
let set_a = recovered.data.get("key_a").expect("key_a must exist");
assert_eq!(
set_a,
&[1usize, 2, 3].iter().copied().collect::<HashSet<_>>()
);
let set_b = recovered.data.get("key_b").expect("key_b must exist");
assert!(set_b.is_empty(), "empty set must survive round-trip");
let set_c = recovered.data.get("key_c").expect("key_c must exist");
assert!(
set_c.contains(&42),
"key_c must contain 42 after round-trip"
);
}
}