Adding values to an object property from another object with the identical definition in JavaScript

I have two different objects that look like this:

var obj1 = {
  fparams: {
    keys: ['a', 'b'],
    pairs: {
      'p': 'qwert'
    }
  },
  qparams: {
    'x': 'xyz'
  }
}

And the second object is:

var obj2 = {
  fparams: {
    keys: ['c', 'd'],
    pairs: {
      'q': 'yuiop'
    }
  },
  qparams: {
    'z': 'zyx'
  }
}

How can I merge the properties from obj2 into obj1?

While working in Angular, I attempted using angular.merge(obj1,obj2), however it didn't merge the 'keys' array, instead replaced it with the values from obj2. Other properties were merged successfully.

This is the desired outcome:

var obj2 = {
  fparams: {
    keys: ['a', 'b', 'c', 'd'],
    pairs: {
      'p': 'qwert',
      'q': 'yuiop'
    }
  },
  qparams: {
    'x': 'xyz',
    'y': 'zyx'
  }
}

The version of Angular I'm using is angular 1.5.8.

Edit : I eventually switched to lodash because it was more convenient to work with and offered many functionalities that I wasn't aware of previously.

Answer №1

Have you thought about leveraging the power of Underscore.js? It offers a handy extend function that achieves the same result.

Answer №2

Using pure JS and the recursive function mergeObjects, you can combine objects like this:

function mergeObjects(obj1, obj2){
  return Object.keys(obj1)
               .reduce(function(result, key){
                         if(Array.isArray(obj1[key])){
                           obj1[key] = obj1[key].concat(obj2[key]);
                         } else if(typeof obj1[key] === "object"){
                           obj1[key] = mergeObjects(obj1[key], obj2[key]);
                         } else {
                           result = Object.assign({}, obj1, obj2);
                         }
                         return result;
                       }, obj1);
}

var objects = [{
             firstParams: {
                         keys : ['a', 'b'],
                         pairs: {
                                 'p': 'qwert'
                                }
                        },
             queryParameters: {
                               'x': 'xyz'
                              }
            },
            {
             firstParams: {
                         keys : ['c', 'd'],
                         pairs: {
                                 'q': 'yuiop'
                                }
                         },
             queryParameters: {
                               'z': 'zyx'
                              }
            }],
  mergedResult = objects.reduce(mergeObjects);
console.log(JSON.stringify(mergedResult,null,2));

Answer №3

When working with lodash, the mergeWith function comes in handy for achieving the desired outcome. Specifically, when dealing with array values, concatenating them is necessary.

var obj1 = {"fparams":{"keys":["a","b"],"pairs":{"p":"qwert"}},"qparams":{"x":"xyz"}}
var obj2 = {"fparams":{"keys":["c","d"],"pairs":{"q":"yuiop"}},"qparams":{"z":"zyx"}}

var result = _.mergeWith(obj1, obj2, function(a, b) {
  if(_.isArray(a)) return a.concat(b)
})

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

Here is an attempt at deep merging through recursion. While this approach may not work on all data structures, it showcases a different method of merging objects.

var obj1 = {"fparams":{"keys":["a","b"],"pairs":{"p":"qwert"}},"qparams":{"x":"xyz"}}
var obj2 = {"fparams":{"keys":["c","d"],"pairs":{"q":"yuiop"}},"qparams":{"z":"zyx"}}

function merge(o1, o2) {
  var result = {}
  for (var i in o1) {
    for (var j in o2) {
      if (i == j && typeof o1[i] == 'object' && typeof o2[j] == 'object') {
        if (Array.isArray(o1[i]) || Array.isArray(o2[j])) {
          result[i] = Array.isArray(o1[i]) ? o1[i].concat(o2[j]) : o2[j].concat(o1[i])
        } else {
          result[i] = Object.assign(result[i] || {}, merge(o1[i], o2[j]))
        }
      }
      if (typeof o1[i] != 'object' || typeof o2[j] != 'object') {
        result[i] = o1[i]
        result[j] = o2[j]
      }

    }
  }
  return result;
}

console.log(JSON.stringify(merge(obj1, obj2), 0, 4))

Answer №4

Here is a custom function that attempts to handle various scenarios, although it may not be as robust as other available libraries:

var combineObjects = function(object1, object2) {
  for (var key in object2) {
    if (object2.hasOwnProperty(key)) {
       if (object1[key] == null) {
           object1[key] = object2[key];
       } else if (object1[key] instanceof Array) {
           if (object2[key] instanceof Array) {
               for (var i = 0; i < object2[key].length; i++) {
                   if (object1[key].indexOf(object2[key]) === -1) {
                       object1[key].push(object2[key][i]);
                   }
               }
           }
       } else if (object1[key] instanceof Object && object2[key] instanceof Object && object1[key].constructor == Object && object2[key] == Object) {
           combineObjects(object1[key], object2[key]);
       }
    }
  }
}

To use this function, you can simply call it with the two objects you want to merge:

combineObjects(object1, object2);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to trigger a function (or directive) specifically when a tab is chosen in AngularJS?

Just starting to learn angularjs and I've created a page with 2 tabs using directives. I'm using $http to fetch json data from my server. My issue is that I don't want to make a request to the server until the user decides to view the other ...

What is the best way to arrange an array of objects based on a specific condition

I have an array of objects that contain properties. My goal is to sort them by status in a specific order: 15, 17, and then 16 using JavaScript. In this array of objects, any object with a status value of 16 should be placed at the end, while the rest s ...

Anticipate the resolution of a promise in javascript & graphql/node

I am currently developing a graphql server and facing an issue with one of the resolvers. The resolver needs to return a URL fetched from the AWS API. Despite trying for hours with promises, async await, I have not been able to make it work yet. Here is w ...

Guide to assigning a string resource as the name of a string array

Is there a way to declare a string-array with a string Resource as its name? <string-array name="@string/a_string_from_resources"> I am wondering if it is possible to use a string Resource to name a string-array in Android? <?xml version="1.0" ...

The ng-include directive in Angular seems to be malfunctioning when trying to include the intended link

Imagine having a hyperlink <a href="#one">Click here</a> and an article: <article id="one"><h2>This is the destination</h2></article> When the hyperlink is clicked, it should take you to the article. However, when mo ...

Only scroll the div if it is not within the visible window

I've been looking at this snippet: The sidebar division is what I'm focusing on right now. I want the div to scroll along as I scroll down the page, but I need it to stop scrolling when its bottom is in view. The same should apply when scrollin ...

Prop validation error: prop type mismatch occurred

My Vue.js countdown isn't displaying the values correctly. Despite defining everything as numbers, I keep getting an error in the console: [Vue warn]: Invalid prop: type check failed for prop "date". Expected Number, got String. I've gone th ...

Steering clear of ng-include while still maintaining versatility in displaying sub-templates

In my project, I have a component that serves as a "blog post", containing various data. To accommodate different content sections, I've developed multiple templates that can be dynamically rendered within the main "blog" template using ng-include. H ...

How to retrieve the outcome of a stored procedure using node.js

Is it possible to retrieve multiple select results from distinct tables (many rows) in just one stored procedure in mysql and then access those results in nodejs? In .NET with SQL Server, we can use "sqlnextresult" for this purpose. VIEW IMAGE FROM STORE ...

Should JavaScript be referenced at the start or generated dynamically?

As I continue working on my small web application, I've noticed that the amount of Javascript is increasing. I'm curious about the best practice for loading/referencing Javascript - should it all be loaded at once at the beginning or dynamically ...

The conventional method for including React import statements

I'm curious if there is a standard convention for writing import statements in React. For instance, I currently have the following: import React, { useState, FormEvent } from 'react'; import Avatar from '@material-ui/core/Avatar'; ...

Is there a way to retrieve all elements from an array by using the .fetch method?

I'm completely new to the world of Ruby and Ruby on Rails. I have some date data stored in an array, and I'm eager to compare each date with the current date. I managed to use the .fetch method to compare one date with Date.today, and it worked p ...

Encountering a 404 error while attempting to upload files with multer in node.js

I am currently developing a website using node.js where users can create small adverts with various information and upload images. I have successfully set up a mongodb database to store the data, but I am encountering a 404 error when trying to upload imag ...

What are some strategies for resolving a parse error in a JSON file?

var personalInfo = { "name": "Belphy Baby", "role": "student", "contacts": { "mobile": "9567166100", "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3654535a465e4f070076515b575f5a1855595b"&g ...

Multiple 'keydown' events are accumulating with Ajax activated

When the search field is focused, I am loading JSON into the browser and then iterating over the JSON objects to find real-time results 'on keydown'. The issue I'm encountering is detailed in the console after the initial block of code Aja ...

jQuery: Gallerific Partially Functioning

Currently, I am attempting to implement the jQuery gallerific plugin on my website located at . The gallery loads correctly, however, both the thumbnail grid and navigation buttons for next/previous images are not functioning as expected. Despite no visi ...

Shiny Exterior using ThreeJS

Trying to achieve a realistic metallic appearance in ThreeJS has been a challenge for me. Despite knowing that I should be using the MeshPhongMaterial material type, I am struggling to configure it properly. My current implementation only results in a pla ...

Passing the unique identifier of a record in NextJS to a function that triggers a modal display

I'm currently facing an issue with my NextJS component that displays a list of people. I have implemented a delete button which triggers a modal to confirm the deletion of a person, but I am struggling with passing the id of the person to be deleted. ...

Storing Polygon Coordinates (GeoJSON) in a MongoDB Database with NodeJS and Mongoose: Step-by-Step Guide

Having trouble storing a Polygon in my MongoDB Database using Mongoose. Despite trying various solutions, I can't seem to get it right. I managed to store coordinates as a String, but not as a geoJSON array representing Polygons. The territory prope ...

Using CKEditor in an AngularJS web application: Tips and tricks

I'm having trouble integrating the ckeditor into an HTML page that's built with angularjs. Despite trying out numerous examples, such as the ng-ckeditor and ckeditor directives, I haven't found a solution that works for me. What I need is ...