json_merge_patch/
lib.rs

1use serde_json::Value;
2
3pub fn json_merge_patch(target: &mut Value, patch: &Value) {
4    match patch {
5        Value::Object(patch_obj) => {
6            if !(target.is_object()
7                || target.is_array() && patch_obj.keys().all(|key| key.parse::<usize>().is_ok()))
8            {
9                *target = Value::Object(serde_json::Map::new());
10            }
11
12            if let Value::Object(target_obj) = target {
13                for (key, value) in patch_obj {
14                    if value.is_null() {
15                        target_obj.remove(key);
16                    } else {
17                        let target_value =
18                            target_obj.entry(key.clone()).or_insert_with(|| Value::Null);
19                        json_merge_patch(target_value, value);
20                    }
21                }
22            } else if let Value::Array(target_arr) = target {
23                for (key, value) in patch_obj {
24                    if let Ok(index) = key.parse::<usize>() {
25                        if value.is_null() && index < target_arr.len() {
26                            target_arr.remove(index);
27                        } else if index < target_arr.len() {
28                            json_merge_patch(&mut target_arr[index], value);
29                        } else {
30                            // Handling the case where the index is greater than the current length of the target array
31                            while target_arr.len() < index {
32                                target_arr.push(Value::Null);
33                            }
34                            target_arr.push(value.clone());
35                        }
36                    }
37                }
38            }
39        }
40        Value::Array(patch_arr) => {
41            *target = serde_json::Value::Array(
42                patch_arr
43                    .clone()
44                    .into_iter()
45                    .filter(|value| !value.is_null())
46                    .collect(),
47            );
48        }
49        _ => *target = patch.clone(),
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_json_merge_patch_should_merge_objects_and_override_field() {
59        let mut target = serde_json::from_str(r#"{"a": "b", "c": {"d": "e", "f": "g"}}"#).unwrap();
60        let patch = serde_json::from_str(r#"{"a": "z", "c": {"f": null}}"#).unwrap();
61
62        json_merge_patch(&mut target, &patch);
63
64        let expected: serde_json::Value =
65            serde_json::from_str(r#"{"a": "z", "c": {"d": "e"}}"#).unwrap();
66        assert_eq!(target, expected);
67    }
68
69    #[test]
70    fn test_json_merge_patch_should_override_field_in_object() {
71        let mut target = serde_json::from_str(r#"{"a": "b"}"#).unwrap();
72        let patch = serde_json::from_str(r#"{"a": "c"}"#).unwrap();
73        let expected: serde_json::Value = serde_json::from_str(r#"{"a": "c"}"#).unwrap();
74
75        json_merge_patch(&mut target, &patch);
76
77        assert_eq!(target, expected);
78    }
79
80    #[test]
81    fn test_json_merge_patch_should_add_field_to_object() {
82        let mut target = serde_json::from_str(r#"{"a": "b"}"#).unwrap();
83        let patch = serde_json::from_str(r#"{"b": "c"}"#).unwrap();
84        let expected: serde_json::Value = serde_json::from_str(r#"{"a": "b", "b": "c"}"#).unwrap();
85
86        json_merge_patch(&mut target, &patch);
87
88        assert_eq!(target, expected);
89    }
90
91    #[test]
92    fn test_json_merge_patch_should_remove_field_from_object() {
93        let mut target = serde_json::from_str(r#"{"a": "b", "b": "c"}"#).unwrap();
94        let patch = serde_json::from_str(r#"{"a": null}"#).unwrap();
95        let expected: serde_json::Value = serde_json::from_str(r#"{"b": "c"}"#).unwrap();
96
97        json_merge_patch(&mut target, &patch);
98
99        assert_eq!(target, expected);
100    }
101
102    #[test]
103    fn test_json_merge_patch_should_override_field_in_array() {
104        let mut target = serde_json::from_str(r#"{"a": ["b"]}"#).unwrap();
105        let patch = serde_json::from_str(r#"{"a": "c"}"#).unwrap();
106        let expected: serde_json::Value = serde_json::from_str(r#"{"a": "c"}"#).unwrap();
107
108        json_merge_patch(&mut target, &patch);
109
110        assert_eq!(target, expected);
111    }
112
113    #[test]
114    fn test_json_merge_patch_should_replace_array_with_scalar() {
115        let mut target = serde_json::from_str(r#"{"a": "c"}"#).unwrap();
116        let patch = serde_json::from_str(r#"{"a": ["b"]}"#).unwrap();
117        let expected: serde_json::Value = serde_json::from_str(r#"{"a": ["b"]}"#).unwrap();
118
119        json_merge_patch(&mut target, &patch);
120
121        assert_eq!(target, expected);
122    }
123
124    #[test]
125    fn test_json_merge_patch_should_merge_objects_in_object() {
126        let mut target = serde_json::from_str(r#"{"a": {"b": "c"}}"#).unwrap();
127        let patch = serde_json::from_str(r#"{"a": {"b": "d", "c": null}}"#).unwrap();
128        let expected: serde_json::Value = serde_json::from_str(r#"{"a": {"b": "d"}}"#).unwrap();
129
130        json_merge_patch(&mut target, &patch);
131
132        assert_eq!(target, expected);
133    }
134
135    #[test]
136    fn test_json_merge_patch_should_replace_array_with_value() {
137        let mut target = serde_json::from_str(r#"{"a": [{"b": "c"}]}"#).unwrap();
138        let patch = serde_json::from_str(r#"{"a": [1]}"#).unwrap();
139        let expected: serde_json::Value = serde_json::from_str(r#"{"a": [1]}"#).unwrap();
140
141        json_merge_patch(&mut target, &patch);
142
143        assert_eq!(target, expected);
144    }
145
146    #[test]
147    fn test_json_merge_patch_should_merge_nested_objects_and_remove_leaf_nodes() {
148        let mut target = serde_json::from_str(r#"{}"#).unwrap();
149        let patch = serde_json::from_str(r#"{"a": {"bb": {"ccc": null}}}"#).unwrap();
150        let expected: serde_json::Value = serde_json::from_str(r#"{"a": {"bb": {}}}"#).unwrap();
151
152        json_merge_patch(&mut target, &patch);
153
154        assert_eq!(target, expected);
155    }
156
157    #[test]
158    fn test_json_merge_patch_should_replace_scalar_with_scalar() {
159        let mut target = serde_json::from_str(r#"{"a": "b"}"#).unwrap();
160        let patch = serde_json::from_str(r#"["c"]"#).unwrap();
161        let expected: serde_json::Value = serde_json::from_str(r#"["c"]"#).unwrap();
162
163        json_merge_patch(&mut target, &patch);
164
165        assert_eq!(target, expected);
166    }
167
168    #[test]
169    fn test_json_merge_patch_should_replace_scalar_with_null() {
170        let mut target = serde_json::from_str(r#"{"a": "foo"}"#).unwrap();
171        let patch = serde_json::Value::Null;
172
173        json_merge_patch(&mut target, &patch);
174
175        assert_eq!(target, serde_json::Value::Null);
176    }
177
178    #[test]
179    fn test_json_merge_patch_should_replace_scalar_with_string() {
180        let mut target = serde_json::from_str(r#"{"a": "foo"}"#).unwrap();
181        let patch = serde_json::from_str(r#""bar""#).unwrap();
182        let expected: serde_json::Value = serde_json::from_str(r#""bar""#).unwrap();
183
184        json_merge_patch(&mut target, &patch);
185
186        assert_eq!(target, expected);
187    }
188
189    #[test]
190    fn test_json_merge_patch_should_merge_null_with_scalar() {
191        let mut target = serde_json::from_str(r#"{"e": null}"#).unwrap();
192        let patch = serde_json::from_str(r#"{"a": 1}"#).unwrap();
193        let expected: serde_json::Value = serde_json::from_str(r#"{"e": null, "a": 1}"#).unwrap();
194
195        json_merge_patch(&mut target, &patch);
196
197        assert_eq!(target, expected);
198    }
199
200    #[test]
201    fn test_json_merge_patch_should_replace_array_with_object() {
202        let mut target = serde_json::from_str(r#"{"a": []}"#).unwrap();
203        let patch = serde_json::from_str(r#"{"a": {"b": "c"}}"#).unwrap();
204        let expected: serde_json::Value = serde_json::from_str(r#"{"a": {"b": "c"}}"#).unwrap();
205
206        json_merge_patch(&mut target, &patch);
207
208        assert_eq!(target, expected);
209    }
210
211    #[test]
212    fn test_json_merge_patch_should_merge_objects_in_array() {
213        let mut target = serde_json::from_str(r#"[{"a": "b"}, {"c": "d"}]"#).unwrap();
214        let patch = serde_json::from_str(r#"{"1": {"e": "f"}}"#).unwrap();
215        let expected: serde_json::Value =
216            serde_json::from_str(r#"[{"a": "b"}, {"c": "d", "e": "f"}]"#).unwrap();
217
218        json_merge_patch(&mut target, &patch);
219
220        assert_eq!(target, expected);
221    }
222
223    #[test]
224    fn test_json_merge_patch_should_replace_object_with_array() {
225        let mut target = serde_json::from_str(r#"{"a": {"b": "c"}}"#).unwrap();
226        let patch = serde_json::from_str(r#"{"a": []}"#).unwrap();
227        let expected: serde_json::Value = serde_json::from_str(r#"{"a": []}"#).unwrap();
228
229        json_merge_patch(&mut target, &patch);
230
231        assert_eq!(target, expected);
232    }
233
234    #[test]
235    fn test_json_merge_patch_should_merge_arrays() {
236        let mut target = serde_json::from_str(r#"["a", "b"]"#).unwrap();
237        let patch = serde_json::from_str(r#"["c", "d"]"#).unwrap();
238        let expected: serde_json::Value = serde_json::from_str(r#"["c", "d"]"#).unwrap();
239
240        json_merge_patch(&mut target, &patch);
241
242        assert_eq!(target, expected);
243    }
244
245    #[test]
246    fn test_json_merge_patch_should_remove_key_from_object() {
247        let mut target = serde_json::from_str(r#"{"a": "b"}"#).unwrap();
248        let patch = serde_json::from_str(r#"{"a": null}"#).unwrap();
249        let expected: serde_json::Value = serde_json::from_str(r#"{}"#).unwrap();
250
251        json_merge_patch(&mut target, &patch);
252
253        assert_eq!(target, expected);
254    }
255
256    #[test]
257    fn test_json_merge_patch_should_remove_index_from_array() {
258        let mut target = serde_json::from_str(r#"["a", "b"]"#).unwrap();
259        let patch = serde_json::from_str(r#"{"1": null}"#).unwrap();
260        let expected: serde_json::Value = serde_json::from_str(r#"["a"]"#).unwrap();
261
262        json_merge_patch(&mut target, &patch);
263
264        assert_eq!(target, expected);
265    }
266
267    #[test]
268    fn test_json_merge_patch_should_remove_array_element() {
269        let mut target = serde_json::from_str(r#"[1, 2, 3]"#).unwrap();
270        let patch = serde_json::from_str(r#"[null, 2]"#).unwrap();
271        let expected: serde_json::Value = serde_json::from_str(r#"[2]"#).unwrap();
272
273        json_merge_patch(&mut target, &patch);
274
275        assert_eq!(target, expected);
276    }
277}