在没有jQuery的情况下在node.js上合并或合并JSON


77

我有多个JSON这样的人

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

它们不是嵌套的或类似的东西。基本上是不同的领域。我需要像这样JSONnode.js中将它们组合为一个:

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

我可以很好地使用jQuery。这是浏览器中的一个有效示例:

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

但是,如果我在node.js中执行此操作,则不希望加载jQuery(这有点用处,加上node.js的jQueryWindows计算机上不起作用)。

那么,有没有一种简单的方法可以执行类似于$.extend()不使用jQuery的事情?


2
如果您正在做这样的事情,则可能需要考虑使用Underscore(可作为Node模块使用)
James Allardice

1
npm install extendNode.js的jQuery.extend的端口
乔尔·普拉

FYI Object.assign可以执行此操作,但是很遗憾,当前不支持。希望有一天很快! developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
刘若英Wooller

1
那不是JSON,您只是使用文字表示法创建标准JS对象。(例如,JSON密钥中的字符串必须为字符串)。当您“合并”这些对象时,它与JSON的关系为零。
UpTheCreek

Answers:


42

正常循环?

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);

这是一个基本的起点。您可能想要添加诸如hasOwnProperty检查之类的内容,或者添加一些逻辑以处理多个源对象具有具有相同标识符的属性的情况。

这是一个有效的例子

旁注:您所说的“ JSON”实际上是普通的JavaScript对象。JSON只是一种文本格式,与JavaScript共享一些语法。


我使用此功能合并两个json。但是最终的json预先加了“ 0”。示例0:{kye:值}。请帮我如何用自己的字符串而不是'0'作为前缀?
萨拉·格瓦里

7
不赞成投票的原因,这是人们(尤其是新手)应定向到经过测试的库的情况之一。
Martin Wawrusch 2014年

121

您应该使用“ Object.assign()

如此简单的浅层合并用例无需重新发明轮子。

Object.assign()方法用于将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

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

甚至来自Node.js的人也这么说

_extend从未打算在内部NodeJS模块之外使用。社区仍然找到并使用了它。它已被弃用,不应在新代码中使用。JavaScript通过附带了非常相似的内置功能Object.assign


更新:

您可以使用点差运算符

8.6版开始,可以在Node.js中本地使用传播运算符。下面的例子:

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

Object.assign 仍然有效。


PS1:如果您实际上对深度合并感兴趣(内部对象数据(任何深度)都以递归方式合并),则可以使用deepmergeAssign -deeplodash.merge之类的包,它们非常小且易于操作使用。

PS2:请记住,Object.assign不适用于Node.js的0.X版本。如果您使用的是其中一个版本(您现在真的不应该使用),则可以使用require("util")._extend上面的Node.js链接中所示的方式-有关更多详细信息,请查看tobymackenzie对相同问题的回答


1
+1对于来这里寻找本机浏览器替代品的任何人,请注意,这是ES6功能,因此尚不十分支持
波阿斯

在上面的Mozilla链接中,添加到Boaz注释中Object.assign,您可以找到一个在浏览器中正常工作的polyfill。
里卡多·诺尔德

3
用一个空的第一个参数调用它,以避免意外损坏您的对象:var obj = Object.assign({}, o1, o2, o3)
pguardiario

57

如果使用节点版本> = 4,请使用Object.assign()(请参阅Ricardo Nolde的答案)。

如果使用节点0.x,则有内置的util._extend:

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

它不做深层复制,一次只允许两个参数,而是内置的。我在关于克隆节点中的对象的问题上看到了这一点:https : //stackoverflow.com/a/15040626

如果您担心使用“私有”方法,可以随时代理它:

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

如果它消失了,请用您自己的实现替换它。这是(大约)它们的实现:

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;
};

5
_extend中的下划线表示私有方法,这意味着它不打算供公共使用。这种方法不仅没有记录,而且任何版本的实现都可能更改,从而影响您的项目。
aaaaaa

3
正如@jimbojw在对链接的答案的评论中提到的那样,Isaacs说:“您可以继续使用util._extends()…它很快就不会出现在任何地方了”。该线程中有进一步的讨论。如果您担心,请通读并为您的项目做出决定。
tobymackenzie 2015年

npm install util-extend
Maciej Krawczyk

1
_extend()功能beeen弃用,取而代之的Object.Assign()- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
brasskazoo

51

extend詹姆斯(James)评论说,下划线是实现这一目标的最简单,最快的方法。

这是使用下划线的示例:

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

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

对象1将获得对象2的属性,并将其返回并分配给目标。您也可以这样做,具体取决于您是否介意对object1进行修改:

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

1
谢谢。但是如果可以的话,我也想避免在node.js中使用下划线。
HP。

1
我只有一个带有express和mailjs的轻量级node.js应用程序。如果我只使用一个函数,只是不想加载其他库。我们的想法仍然很酷。谢谢。
HP。

10
当心,下划线的扩展仅在第一级。它不能合并主题。
2014年

15

使用merge

$ npm install merge

样例代码:

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

2
优秀!感谢您分享。
Gor 2014年

12

我看到这个线程太旧了,但是我在这里出于日志记录的目的回答了我。

在上面的评论之一中,您提到要在依赖项列表中具有“ connect”库的项目中使用“ express”。实际上,“ connect.utils”库包含执行此操作的“ merge”方法。因此,您可以使用第三方实现,而无需添加任何新的第三方库。


11

这是合并JSON的简单解决方案。我做了以下。

  • 使用将每个JSON转换为字符串JSON.stringify(object)
  • 使用+运算符连接所有JSON字符串。
  • 替换模式/}{/g","
  • 将结果字符串解析回JSON对象

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

合并后的JSON将是

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

如果双引号(值)中包含{或},是否可以使用?我总是很犹豫要修改字符串。
HP。

@HP。是的,它将起作用。这是非常简单的正则表达式/} {/,无需担心字符串操作。:-)
Manu K Mohan

1
不幸的是,object2 = {}由于要解析的最终字符为,因此无法使用,}。替换后添加即可解决:.replace(/,}^/, '}')
htaidirt 2013年

3
使用任意数量的参数,无论是否有gist.github.com/rxaviers/6734630
Rafael Xavier

@RafaelXavier的道具他的要旨将这个答案变成了可用的功能。
scarver2

3

您还可以使用这种称为吸收的轻量级npm软件包

它是27行代码(1kb),并使用递归执行深度对象合并。

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' }

如果源对象中不存在值,也可以使用它进行克隆或仅传输值,有关方法的详细说明,请参见所提供的链接。



3

在Node.js中有一种简单的方法

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

为了结合/扩展这一点,我们可以...在ECMA6中使用运算符

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

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

console.log(result)


2

如果您需要特殊的行为,例如嵌套对象扩展或数组替换,则可以使用Node.js的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}

1
准确地说:Extendify不是由Node.js提供的。它是Node.js的软件包。
Leo Gerber

2

Lodash是这些实用程序的另一个强大的工具带选项。参见:(_.merge()这是递归的)

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 }] } 

2

使用传播算子。自8.6版开始在Node中受支持

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

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

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


1
嗨,Khaled,您应该尝试解释点差算子的功能,因为这将改善您的职位。说明远比仅说明代码要好。它也是已经发布的答案的重复。
R. Chappell '18

1

您可以使用Lodash

const _ = require('lodash');

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

0

下面的代码将帮助您合并具有嵌套对象的两个JSON对象。

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;
}

0

为了避免更改目标,此处提供了一种来自正确解决方案的更好方法:

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

0

您可以内联完成此操作,而无需更改任何变量,如下所示:

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

-3

object1object2是两个JSON对象。

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

object1.push(object2);

这将简单地附加object2object1

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

这不是OP所要求的。您正在展示如何构建JSON对象数组。OP要求一种将多个JSON对象中的key:value对组合成一个对象的方法。
David Makogon '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.