conjure_oxide/utils/
json.rs1use serde_json::Value;
2
3fn json_value_cmp(a: &Value, b: &Value) -> std::cmp::Ordering {
8 match (a, b) {
9 (Value::Null, Value::Null) => std::cmp::Ordering::Equal,
10 (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
11 (Value::String(a), Value::String(b)) => a.cmp(b),
12 (Value::Number(a), Value::Number(b)) => {
13 let af = a.as_f64().unwrap_or_default();
14 let bf = b.as_f64().unwrap_or_default();
15 af.total_cmp(&bf)
16 }
17 (Value::Array(a), Value::Array(b)) => {
18 for (a, b) in a.iter().zip(b.iter()) {
19 let cmp = json_value_cmp(a, b);
20 if cmp != std::cmp::Ordering::Equal {
21 return cmp;
22 }
23 }
24 std::cmp::Ordering::Equal
25 }
26 _ => a.to_string().cmp(&b.to_string()),
27 }
28}
29
30pub fn sort_json_variables(value: &Value) -> Value {
33 match value {
34 Value::Array(vars) => {
35 let mut vars_sorted = vars.clone();
36 vars_sorted.sort_by(json_value_cmp);
37 Value::Array(vars_sorted)
38 }
39 _ => value.clone(),
40 }
41}
42
43pub fn sort_json_object(value: &Value, sort_arrays: bool) -> Value {
49 match value {
50 Value::Object(obj) => {
51 let mut ordered: Vec<(String, Value)> = obj
52 .iter()
53 .map(|(k, v)| {
54 if k == "variables" {
55 (k.clone(), sort_json_variables(v))
56 } else {
57 (k.clone(), sort_json_object(v, sort_arrays))
58 }
59 })
60 .collect();
61
62 ordered.sort_by(|a, b| a.0.cmp(&b.0));
63 Value::Object(ordered.into_iter().collect())
64 }
65 Value::Array(arr) => {
66 let mut arr: Vec<Value> = arr
67 .iter()
68 .map(|val| sort_json_object(val, sort_arrays))
69 .collect();
70
71 if sort_arrays {
72 arr.sort_by(json_value_cmp);
73 }
74
75 Value::Array(arr)
76 }
77 _ => value.clone(),
78 }
79}