1use serde_json::Value;
10
11pub fn merge_value(base: &mut Value, overlay: Value) {
13 match (base, overlay) {
14 (Value::Object(b), Value::Object(o)) => {
15 for (k, v) in o {
16 match b.get_mut(&k) {
17 Some(existing) => merge_value(existing, v),
18 None => {
19 b.insert(k, v);
20 }
21 }
22 }
23 }
24 (slot, overlay) => *slot = overlay,
25 }
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31 use serde_json::json;
32
33 #[test]
34 fn scalar_overlay_replaces() {
35 let mut base = json!({"a": 1, "b": 2});
36 merge_value(&mut base, json!({"b": 99}));
37 assert_eq!(base, json!({"a": 1, "b": 99}));
38 }
39
40 #[test]
41 fn objects_merge_recursively() {
42 let mut base = json!({"auth": {"type": "Bearer", "token": "x"}, "path": "/v1"});
43 merge_value(&mut base, json!({"auth": {"token": "y"}}));
44 assert_eq!(
45 base,
46 json!({"auth": {"type": "Bearer", "token": "y"}, "path": "/v1"})
47 );
48 }
49
50 #[test]
51 fn arrays_replace_wholesale() {
52 let mut base = json!({"tags": ["a", "b"]});
53 merge_value(&mut base, json!({"tags": ["c"]}));
54 assert_eq!(base, json!({"tags": ["c"]}));
55 }
56
57 #[test]
58 fn null_overlay_replaces() {
59 let mut base = json!({"x": {"y": 1}});
60 merge_value(&mut base, json!({"x": null}));
61 assert_eq!(base, json!({"x": null}));
62 }
63
64 #[test]
65 fn overlay_adds_new_keys() {
66 let mut base = json!({"a": 1});
67 merge_value(&mut base, json!({"b": 2}));
68 assert_eq!(base, json!({"a": 1, "b": 2}));
69 }
70
71 #[test]
72 fn object_into_non_object_replaces() {
73 let mut base = json!({"path": "/v1"});
74 merge_value(&mut base, json!({"path": {"foo": "bar"}}));
75 assert_eq!(base, json!({"path": {"foo": "bar"}}));
76 }
77
78 #[test]
79 fn non_object_into_object_replaces() {
80 let mut base = json!({"path": {"foo": "bar"}});
81 merge_value(&mut base, json!({"path": "/v1"}));
82 assert_eq!(base, json!({"path": "/v1"}));
83 }
84
85 #[test]
86 fn deeply_nested_merges() {
87 let mut base = json!({"a": {"b": {"c": 1, "d": 2}, "x": 10}});
88 merge_value(&mut base, json!({"a": {"b": {"c": 99, "e": 3}}}));
89 assert_eq!(
90 base,
91 json!({"a": {"b": {"c": 99, "d": 2, "e": 3}, "x": 10}})
92 );
93 }
94}