1use serde_json::Value;
32
33#[must_use]
53pub fn json_merge_patch(target: &Value, patch: &Value) -> Value {
54 let mut result = target.clone();
55 merge_patch_mut(&mut result, patch);
56 result
57}
58
59pub fn merge_patch_mut(target: &mut Value, patch: &Value) {
61 if !patch.is_object() {
63 *target = patch.clone();
64 return;
65 }
66
67 if !target.is_object() {
69 *target = Value::Object(serde_json::Map::new());
70 }
71
72 let target_obj = target.as_object_mut().expect("target should be object");
73 let patch_obj = patch.as_object().expect("patch should be object");
74
75 for (key, patch_value) in patch_obj {
76 if patch_value.is_null() {
77 target_obj.remove(key);
79 } else if patch_value.is_object() {
80 let target_value = target_obj
82 .entry(key.clone())
83 .or_insert_with(|| Value::Object(serde_json::Map::new()));
84 merge_patch_mut(target_value, patch_value);
85 } else {
86 target_obj.insert(key.clone(), patch_value.clone());
88 }
89 }
90}
91
92#[must_use]
100pub fn merge_patch_to_value(source: &Value, target: &Value) -> Value {
101 generate_merge_patch(source, target)
102}
103
104fn generate_merge_patch(source: &Value, target: &Value) -> Value {
106 match (source, target) {
107 (Value::Object(src), Value::Object(tgt)) => {
109 let mut patch = serde_json::Map::new();
110
111 for key in src.keys() {
113 if !tgt.contains_key(key) {
114 patch.insert(key.clone(), Value::Null);
115 }
116 }
117
118 for (key, tgt_value) in tgt {
120 match src.get(key) {
121 Some(src_value) => {
122 if src_value != tgt_value {
124 let nested_patch = generate_merge_patch(src_value, tgt_value);
125 if nested_patch != Value::Object(serde_json::Map::new()) {
127 patch.insert(key.clone(), nested_patch);
128 }
129 }
130 }
131 None => {
132 patch.insert(key.clone(), tgt_value.clone());
134 }
135 }
136 }
137
138 Value::Object(patch)
139 }
140
141 _ => {
143 if source == target {
144 Value::Object(serde_json::Map::new()) } else {
146 target.clone()
147 }
148 }
149 }
150}
151
152#[must_use]
156pub fn merge_many(documents: &[Value]) -> Value {
157 documents
158 .iter()
159 .fold(Value::Object(serde_json::Map::new()), |acc, doc| {
160 json_merge_patch(&acc, doc)
161 })
162}
163
164#[must_use]
168pub fn deep_merge(base: &Value, overlay: &Value) -> Value {
169 match (base, overlay) {
170 (Value::Object(base_obj), Value::Object(overlay_obj)) => {
171 let mut result = base_obj.clone();
172
173 for (key, overlay_value) in overlay_obj {
174 let merged = result.get(key).map_or_else(
175 || overlay_value.clone(),
176 |base_value| deep_merge(base_value, overlay_value),
177 );
178 result.insert(key.clone(), merged);
179 }
180
181 Value::Object(result)
182 }
183 (_, overlay) => overlay.clone(),
185 }
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191 use serde_json::json;
192
193 #[test]
194 fn test_merge_patch_add_field() {
195 let target = json!({"a": "b"});
196 let patch = json!({"c": "d"});
197 let result = json_merge_patch(&target, &patch);
198 assert_eq!(result, json!({"a": "b", "c": "d"}));
199 }
200
201 #[test]
202 fn test_merge_patch_replace_field() {
203 let target = json!({"a": "b"});
204 let patch = json!({"a": "c"});
205 let result = json_merge_patch(&target, &patch);
206 assert_eq!(result, json!({"a": "c"}));
207 }
208
209 #[test]
210 fn test_merge_patch_delete_field() {
211 let target = json!({"a": "b", "c": "d"});
212 let patch = json!({"a": null});
213 let result = json_merge_patch(&target, &patch);
214 assert_eq!(result, json!({"c": "d"}));
215 }
216
217 #[test]
218 fn test_merge_patch_nested() {
219 let target = json!({
220 "title": "Hello",
221 "author": {
222 "name": "John",
223 "email": "john@example.com"
224 }
225 });
226 let patch = json!({
227 "title": "New Title",
228 "author": {
229 "email": null,
230 "twitter": "@john"
231 }
232 });
233 let result = json_merge_patch(&target, &patch);
234 assert_eq!(
235 result,
236 json!({
237 "title": "New Title",
238 "author": {
239 "name": "John",
240 "twitter": "@john"
241 }
242 })
243 );
244 }
245
246 #[test]
247 fn test_merge_patch_replace_object_with_value() {
248 let target = json!({"a": {"b": "c"}});
249 let patch = json!({"a": "value"});
250 let result = json_merge_patch(&target, &patch);
251 assert_eq!(result, json!({"a": "value"}));
252 }
253
254 #[test]
255 fn test_merge_patch_replace_value_with_object() {
256 let target = json!({"a": "value"});
257 let patch = json!({"a": {"b": "c"}});
258 let result = json_merge_patch(&target, &patch);
259 assert_eq!(result, json!({"a": {"b": "c"}}));
260 }
261
262 #[test]
263 fn test_merge_patch_array_replacement() {
264 let target = json!({"arr": [1, 2, 3]});
266 let patch = json!({"arr": [4, 5]});
267 let result = json_merge_patch(&target, &patch);
268 assert_eq!(result, json!({"arr": [4, 5]}));
269 }
270
271 #[test]
272 fn test_merge_patch_non_object_patch() {
273 let target = json!({"a": "b"});
274 let patch = json!("string");
275 let result = json_merge_patch(&target, &patch);
276 assert_eq!(result, json!("string"));
277 }
278
279 #[test]
280 fn test_merge_patch_to_non_object_target() {
281 let target = json!("string");
282 let patch = json!({"a": "b"});
283 let result = json_merge_patch(&target, &patch);
284 assert_eq!(result, json!({"a": "b"}));
285 }
286
287 #[test]
288 fn test_generate_merge_patch_add() {
289 let source = json!({"a": "b"});
290 let target = json!({"a": "b", "c": "d"});
291 let patch = merge_patch_to_value(&source, &target);
292 assert_eq!(patch, json!({"c": "d"}));
293 }
294
295 #[test]
296 fn test_generate_merge_patch_remove() {
297 let source = json!({"a": "b", "c": "d"});
298 let target = json!({"a": "b"});
299 let patch = merge_patch_to_value(&source, &target);
300 assert_eq!(patch, json!({"c": null}));
301 }
302
303 #[test]
304 fn test_generate_merge_patch_modify() {
305 let source = json!({"a": "b"});
306 let target = json!({"a": "c"});
307 let patch = merge_patch_to_value(&source, &target);
308 assert_eq!(patch, json!({"a": "c"}));
309 }
310
311 #[test]
312 fn test_generate_merge_patch_nested() {
313 let source = json!({"outer": {"a": 1, "b": 2}});
314 let target = json!({"outer": {"a": 1, "c": 3}});
315 let patch = merge_patch_to_value(&source, &target);
316 assert_eq!(patch, json!({"outer": {"b": null, "c": 3}}));
317 }
318
319 #[test]
320 fn test_generate_merge_patch_identical() {
321 let source = json!({"a": "b", "c": [1, 2, 3]});
322 let patch = merge_patch_to_value(&source, &source);
323 assert_eq!(patch, json!({}));
324 }
325
326 #[test]
327 fn test_roundtrip() {
328 let source = json!({
329 "name": "Test",
330 "value": 42,
331 "nested": {"a": 1, "b": 2},
332 "arr": [1, 2, 3]
333 });
334
335 let target = json!({
336 "name": "Modified",
337 "nested": {"a": 1, "c": 3},
338 "arr": [4, 5],
339 "new_field": true
340 });
341
342 let patch = merge_patch_to_value(&source, &target);
343 let result = json_merge_patch(&source, &patch);
344 assert_eq!(result, target);
345 }
346
347 #[test]
348 fn test_merge_many() {
349 let docs = vec![json!({"a": 1}), json!({"b": 2}), json!({"a": 10, "c": 3})];
350 let result = merge_many(&docs);
351 assert_eq!(result, json!({"a": 10, "b": 2, "c": 3}));
352 }
353
354 #[test]
355 fn test_merge_many_empty() {
356 let docs: Vec<Value> = vec![];
357 let result = merge_many(&docs);
358 assert_eq!(result, json!({}));
359 }
360
361 #[test]
362 fn test_deep_merge() {
363 let base = json!({
364 "a": 1,
365 "nested": {"x": 10, "y": 20}
366 });
367 let overlay = json!({
368 "b": 2,
369 "nested": {"y": 200, "z": 30}
370 });
371 let result = deep_merge(&base, &overlay);
372 assert_eq!(
373 result,
374 json!({
375 "a": 1,
376 "b": 2,
377 "nested": {"x": 10, "y": 200, "z": 30}
378 })
379 );
380 }
381
382 #[test]
383 fn test_deep_merge_null_preserved() {
384 let base = json!({"a": 1});
386 let overlay = json!({"a": null});
387 let result = deep_merge(&base, &overlay);
388 assert_eq!(result, json!({"a": null}));
389 }
390
391 #[test]
392 fn test_rfc7396_examples() {
393 let target = json!({"a": "b"});
397 let patch = json!({"a": "c"});
398 assert_eq!(json_merge_patch(&target, &patch), json!({"a": "c"}));
399
400 let target = json!({"a": "b"});
402 let patch = json!({"b": "c"});
403 assert_eq!(
404 json_merge_patch(&target, &patch),
405 json!({"a": "b", "b": "c"})
406 );
407
408 let target = json!({"a": "b"});
410 let patch = json!({"a": null});
411 assert_eq!(json_merge_patch(&target, &patch), json!({}));
412
413 let target = json!({"a": "b", "b": "c"});
415 let patch = json!({"a": null});
416 assert_eq!(json_merge_patch(&target, &patch), json!({"b": "c"}));
417
418 let target = json!({"a": ["b"]});
420 let patch = json!({"a": "c"});
421 assert_eq!(json_merge_patch(&target, &patch), json!({"a": "c"}));
422
423 let target = json!({"a": "c"});
425 let patch = json!({"a": ["b"]});
426 assert_eq!(json_merge_patch(&target, &patch), json!({"a": ["b"]}));
427
428 let target = json!({"a": {"b": "c"}});
430 let patch = json!({"a": {"b": "d", "c": null}});
431 assert_eq!(json_merge_patch(&target, &patch), json!({"a": {"b": "d"}}));
432
433 let target = json!({"a": [{"b": "c"}]});
435 let patch = json!({"a": [1]});
436 assert_eq!(json_merge_patch(&target, &patch), json!({"a": [1]}));
437 }
438}