serde_ordered_collections/
map.rs1use serde::Serialize;
2use std::collections::BTreeMap;
3
4pub fn sorted_serialize<S, K, V, M>(map: M, s: S) -> Result<S::Ok, S::Error>
5where
6 M: IntoIterator<Item = (K, V)>,
7 S: serde::Serializer,
8 K: Ord + Serialize + Clone,
9 V: Serialize + Clone,
10{
11 let ordered_map: BTreeMap<K, V> = map.into_iter().collect();
12 Serialize::serialize(&ordered_map, s)
13}
14
15#[cfg(test)]
16mod tests {
17 #![allow(non_snake_case)]
18
19 use serde_derive::{Deserialize, Serialize};
20 use std::collections::HashMap;
21
22 #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
23 struct SampleData {
24 #[serde(flatten, serialize_with = "super::sorted_serialize")]
25 values: HashMap<String, String>,
26 }
27
28 #[test]
29 fn serde_roundtrip__produces_matching_data() {
30 let data = SampleData {
32 values: {
33 let mut map = HashMap::new();
34 map.insert("foo".into(), "bar".into());
35 map.insert("abc".into(), "def".into());
36 map.insert("123".into(), "456".into());
37
38 map
39 },
40 };
41
42 let string = serde_yaml::to_string(&data).unwrap();
44
45 let deserialized_data: SampleData = serde_yaml::from_str(&string).unwrap();
47 assert_eq!(data, deserialized_data);
48 }
49
50 #[test]
51 fn yaml_to_string__produces_correctly_sorted_order_consistently() {
52 for _i in 0..100 {
53 let data = SampleData {
55 values: {
56 let mut map = HashMap::new();
57 map.insert("d".into(), "jkl".into());
58 map.insert("a".into(), "abc".into());
59 map.insert("e".into(), "mno".into());
60 map.insert("c".into(), "ghi".into());
61 map.insert("b".into(), "def".into());
62
63 map
64 },
65 };
66
67 let string = serde_yaml::to_string(&data).unwrap();
69
70 assert_eq!(
72 string,
73 r###"---
74a: abc
75b: def
76c: ghi
77d: jkl
78e: mno
79"###
80 );
81 }
82 }
83}