Deep Merge of Two Objects

Updated on 21 May, 2025
Deep Merge of Two Objects header image

Problem Statement

In the given task, we are required to merge two JSON values obj1 and obj2 into a unified result based on certain merging rules. These rules differ based on the types of the values involved (object, array, or other). Specifically, when both values are objects, the keys from both objects are considered, and if they overlap, the values are merged recursively. If they are arrays, elements are merged up to the length of the longer array with the same depth-first strategy. For all other data types, the resultant value is simply obj2. This implies a complex merging logic that needs to handle different data structures and their nested combinations appropriately.

Examples

Example 1

Input:

obj1 = {"a": 1, "c": 3}, obj2 = {"a": 2, "b": 2}

Output:

{"a": 2, "c": 3, "b": 2}

Explanation:

The value of obj1["a"] changed to 2 because if both objects have the same key and their value is not an array or object then we change the obj1 value to the obj2 value. Key "b" with value was added to obj1 as it doesn't exist in obj1.

Example 2

Input:

obj1 = [{}, 2, 3], obj2 = [[], 5]

Output:

[[], 5, 3]

Explanation:

result[0] = obj2[0] because obj1[0] and obj2[0] have different types. result[2] = obj1[2] because obj2[2] does not exist.

Example 3

Input:

obj1 = {"a": 1, "b": {"c": [1 , [2, 7], 5], "d": 2}},
obj2 = {"a": 1, "b": {"c": [6, [6], [9]], "e": 3}}

Output:

{"a": 1, "b": {"c": [6, [6, 7], [9]], "d": 2, "e": 3}}

Explanation:

Arrays obj1["b"]["c"] and obj2["b"]["c"] have been merged in way that obj2 values overwrite obj1 values deeply only if they are not arrays or objects.
obj2["b"]["c"] has key "e" that obj1 doesn't have so it's added to obj1.

Example 4

Input:

obj1 = true, obj2 = null

Output:

null

Constraints

  • obj1 and obj2 are valid JSON values
  • 1 <= JSON.stringify(obj1).length <= 5 * 105
  • 1 <= JSON.stringify(obj2).length <= 5 * 105

Approach and Intuition

The merging process can be visualized as blending two data structures where the input determines the output in the following detailed way:

  1. Handling Objects:

    • Traverse each key in both objects.
    • If a key exists in both objects:
      • Recursively merge their associated values.
    • If a key exists in only one object:
      • Include the key-value pair in the result as is from the respective object.
  2. Handling Arrays:

    • Determine the length of the resultant array which is the maximum length among both given arrays.
    • Traverse element-wise up to this length:
      • If an element position exists in both arrays, merge them using the same deep merge logic for objects.
      • If an element is absent in one of the arrays but present in the other, it is retained in the result at its respective position.
  3. For Other Data Types:

    • Directly assign obj2 as result which could range over booleans, null, or other primaries.

The utility in merging complex data structures such as JSON objects and arrays arises in various applications, then managing configurations, or combining data from multiple sources. The merging rules and behavior need special attention to depth and type of data elements to ensure correct results and avoid unintended data overriding or loss. Moreover, handling large JSON data (as inferred from constraints) requires efficient management of recursive depth and memory, suggesting that optimized traversal and memory handling strategies are essential for practical implementations.

Solutions

  • JavaScript
js
var mergeObjects = function(source, target) {
  if (typeof source !== 'object' || typeof target !== 'object' || Array.isArray(source) !== Array.isArray(target)) {
    return target;
  }

  if (source === null || target === null) {
    return target;
  }

  const result = source;

  for (const property in target) {
    if (property in result) {
      result[property] = mergeObjects(result[property], target[property]);
      continue;
    }

    result[property] = target[property];
  }

  return result;
};

In this solution, JavaScript is used to implement a function mergeObjects that deeply merges two objects, source and target. The function handles various conditions and intricacies associated with JavaScript objects, such as checking for type mismatches and handling null values.

Here's how the function works:

  1. Initially, it checks if both source and target are objects and ensures they are not arrays, or if they are arrays, they must both be arrays. If these conditions are not met, target is returned directly.
  2. It also checks if either source or target is null, returning target in such a case to prevent errors when accessing properties on null.
  3. The function iterates over each property of target. If the property also exists in source, the function recursively merges these properties. Otherwise, the property from target is directly applied to the result.
  4. The merge results in source being modified directly, and it is returned at the end of the function.

This approach allows nested properties within the objects to be merged thoroughly, preserving nested structures and providing a comprehensive merging capability. The method modifies the source object in-place, making it both memory efficient (by avoiding the creation of new objects) and straightforward for updates directly on the source object.

Comments

No comments yet.