1use serde_json::Value;
4
5#[must_use]
13pub fn sorted_json(value: &Value) -> String {
14 sorted(value).to_string()
15}
16
17fn sorted(value: &Value) -> Value {
18 match value {
19 Value::Object(map) => {
20 let mut entries: Vec<(&String, &Value)> = map.iter().collect();
21 entries.sort_unstable_by(|a, b| a.0.cmp(b.0));
22 Value::Object(
23 entries
24 .into_iter()
25 .map(|(key, item)| (key.clone(), sorted(item)))
26 .collect(),
27 )
28 }
29 Value::Array(items) => Value::Array(items.iter().map(sorted).collect()),
30 other => other.clone(),
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[test]
41 fn key_order_does_not_reach_the_text() {
42 let a: Value = serde_json::from_str(r#"{"b":1,"a":{"d":[{"f":1,"e":2}],"c":2}}"#).unwrap();
43 let b: Value = serde_json::from_str(r#"{"a":{"c":2,"d":[{"e":2,"f":1}]},"b":1}"#).unwrap();
44 assert_eq!(
45 sorted_json(&a),
46 r#"{"a":{"c":2,"d":[{"e":2,"f":1}]},"b":1}"#
47 );
48 assert_eq!(sorted_json(&a), sorted_json(&b));
49 }
50}