Combine or merge JSON on node.js without jQuery


I have multiple JSON like those

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

They are not nesting or anything like that. Just basically different fields. I need to combine them into one single JSON in node.js like this:

{name: "John", location: "San Jose"}

I can use jQuery just fine. Here is a working example in the browser:

http://jsfiddle.net/qhoc/agp54/

But if I do this in node.js, I don't want to load jQuery (which is a bit over use, plus node.js' jQuery doesn't work on my Windows machine).

So is there a simple way to do things similar to $.extend() without jQuery?

A normal loop?

function extend(target) {
    var sources = [].slice.call(arguments, 1);
    sources.forEach(function (source) {
        for (var prop in source) {
            target[prop] = source[prop];
        }
    });
    return target;
}

var object3 = extend({}, object1, object2);

That's a basic starting point. You may want to add things like a hasOwnProperty check, or add some logic to handle the case where multiple source objects have a property with the same identifier.

Here's a working example.

Side note: what you are referring to as "JSON" are actually normal JavaScript objects. JSON is simply a text format that shares some syntax with JavaScript.


You should use "Object.assign()"

There's no need to reinvent the wheel for such a simple use case of shallow merging.

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed

Even the folks from Node.js say so:

_extend was never intended to be used outside of internal NodeJS modules. The community found and used it anyway. It is deprecated and should not be used in new code. JavaScript comes with very similar built-in functionality through Object.assign.


Update:

You could use the spread operator

Since version 8.6, it's possible to natively use the spread operator in Node.js. Example below:

let o1 = { a: 1 };
let o2 = { b: 2 };
let obj = { ...o1, ...o2 }; // { a: 1, b: 2 }

Object.assign still works, though.


PS1: If you are actually interested in deep merging (in which internal object data -- in any depth -- is recursively merged), you can use packages like deepmerge, assign-deep or lodash.merge, which are pretty small and simple to use.

PS2: Keep in mind that Object.assign doesn't work with 0.X versions of Node.js. If you are working with one of those versions (you really shouldn't by now), you could use require("util")._extend as shown in the Node.js link above -- for more details, check tobymackenzie's answer to this same question.


If using Node version >= 4, use Object.assign() (see Ricardo Nolde's answer).

If using Node 0.x, there is the built in util._extend:

var extend = require('util')._extend
var o = extend({}, {name: "John"});
extend(o,  {location: "San Jose"});

It doesn't do a deep copy and only allows two arguments at a time, but is built in. I saw this mentioned on a question about cloning objects in node: https://stackoverflow.com/a/15040626.

If you're concerned about using a "private" method, you could always proxy it:

// myutil.js
exports.extend = require('util')._extend;

and replace it with your own implementation if it ever disappears. This is (approximately) their implementation:

exports.extend = function(origin, add) {
    if (!add || (typeof add !== 'object' && add !== null)){
        return origin;
    }

    var keys = Object.keys(add);
    var i = keys.length;
    while(i--){
        origin[keys[i]] = add[keys[i]];
    }
    return origin;
};

Underscore's extend is the easiest and quickest way to achieve this, like James commented.

Here's an example using underscore:

var _ = require('underscore'), // npm install underscore to install
  object1 = {name: "John"},
  object2 = {location: "San Jose"};

var target = _.extend(object1, object2);

object 1 will get the properties of object2 and be returned and assigned to target. You could do it like this as well, depending on whether you mind object1 being modified:

var target = {};
_.extend(target, object1, object2);

Use merge.

$ npm install merge

Sample code:

var merge = require('merge'), // npm install -g merge
    original, cloned;

console.log(

    merge({ one: 'hello' }, { two: 'world' })

); // {"one": "hello", "two": "world"}

original = { x: { y: 1 } };

cloned = merge(true, original);

cloned.x.y++;

console.log(original.x.y, cloned.x.y); // 1, 2

I see that this thread is too old, but I put my answer here just in logging purposes.

In one of the comments above you mentioned that you wanted to use 'express' in your project which has 'connect' library in the dependency list. Actually 'connect.utils' library contains a 'merge' method that does the trick. So you can use the 3rd party implementation without adding any new 3rd party libraries.


Here is simple solution, to merge JSON. I did the following.

  • Convert each of the JSON to strings using JSON.stringify(object).
  • Concatenate all the JSON strings using + operator.
  • Replace the pattern /}{/g with ","
  • Parse the result string back to JSON object

    var object1 = {name: "John"};
    var object2 = {location: "San Jose"};
    var merged_object = JSON.parse((JSON.stringify(object1) + JSON.stringify(object2)).replace(/}{/g,","))
    

The resulting merged JSON will be

{name: "John", location: "San Jose"}

You can also use this lightweight npm package called absorb

It is 27 lines of code, 1kb and uses recursion to perform deep object merges.

var absorb = require('absorb');
var obj1, obj2;

obj1 = { foo: 123, bar: 456 };
obj2 = { bar: 123, key: 'value' }

absorb(obj1, obj2);

console.log(obj1); // Output: { foo: 123, bar: 123, key: 'value' }

You can also use it to make a clone or only transfer values if they don't exist in the source object, how to do this is detailed in the link provided.


There is an easy way of doing it in Node.js

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

To combine/extend this we can use ... operator in ECMA6

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

var result = {
  ...object1,
  ...object2
}

console.log(result)


If you need special behaviors like nested object extension or array replacement you can use Node.js's extendify.

var extendify = require('extendify');

_.extend = extendify({
    inPlace: false,
    arrays : 'replace',
    isDeep: true
});

obj1 = {
    a:{
        arr: [1,2]
    },
    b: 4
};

obj2 = {
    a:{
        arr: [3]
    }
};

res = _.extend(obj1,obj2);
console.log(JSON.stringify(res)); //{'a':{'arr':[3]},'b':4}

Lodash is a another powerful tool-belt option for these sorts of utilities. See: _.merge() (which is recursive)

var object = {
  'a': [{ 'b': 2 }, { 'd': 4 }]
};
var other = {
  'a': [{ 'c': 3 }, { 'e': 5 }]
}; 
_.merge(object, other);
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } 

It can easy be done using Object.assign() method -

 var object1 = {name: "John"};
 var object2 = {location: "San Jose"};
 var object3 = Object.assign(object1,object2);
 console.log(object3);

now object3 is { name: 'John', location: 'San Jose' }


Use spread operator. It is supported in Node since version 8.6

const object1 = {name: "John"};
const object2 = {location: "San Jose"};

const obj = {...object1, ...object2}

console.log(obj)
//   {
//     "name": "John",
//     "location": "San Jose"
//   }


The below code will help you to merge two JSON object which has nested objects.

function mergeJSON(source1,source2){
    /*
     * Properties from the Souce1 object will be copied to Source2 Object.
     * Note: This method will return a new merged object, Source1 and Source2 original values will not be replaced.
     * */
    var mergedJSON = Object.create(source2);// Copying Source2 to a new Object

    for (var attrname in source1) {
        if(mergedJSON.hasOwnProperty(attrname)) {
          if ( source1[attrname]!=null && source1[attrname].constructor==Object ) {
              /*
               * Recursive call if the property is an object,
               * Iterate the object and set all properties of the inner object.
              */
              mergedJSON[attrname] = zrd3.utils.mergeJSON(source1[attrname], mergedJSON[attrname]);
          } 

        } else {//else copy the property from source1
            mergedJSON[attrname] = source1[attrname];

        }
      }

      return mergedJSON;
}

You can use Lodash

const _ = require('lodash');

let firstObject = {'email' : '[email protected]};
let secondObject = { 'name' : { 'first':message.firstName } };
_.merge(firstObject, secondObject)

A better approach from the correct solution here in order to not alter target:

function extend(){
  let sources = [].slice.call(arguments, 0), result = {};
  sources.forEach(function (source) {
    for (let prop in source) {
      result[prop] = source[prop];
    }
  });
  return result;
}

You can do it inline, without changing any variables like this:

let obj1 = { name: 'John' };
let obj2 = { surname: 'Smith' };
let obj = Object.assign({}, obj1, obj2); // { name: 'John', surname: 'Smith' }

Let object1 and object2 be two JSON object.

var object1 = [{"name": "John"}];
var object2 = [{"location": "San Jose"}];

object1.push(object2);

This will simply append object2 in object1:

[{"name":"John"},{"location":"San Jose"}]