【问题标题】:Combine or merge JSON on node.js without jQuery在没有 jQuery 的情况下在 node.js 上合并或合并 JSON
【发布时间】:2013-02-05 03:50:14
【问题描述】:

我有多个类似的JSON

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

它们不是嵌套或类似的东西。只是基本上不同的领域。我需要在 node.js 中将它们组合成一个 JSON,如下所示:

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

我可以使用 jQuery 就好了。这是浏览器中的一个工作示例:

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

但如果我在 node.js 中执行此操作,我不想加载 jQuery(这有点过度使用,加上 node.js' jQuery 不会不能在我的 Windows 机器上工作)。

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

【问题讨论】:

标签: javascript jquery json node.js


【解决方案1】:

正常循环?

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 检查之类的内容,或者添加一些逻辑来处理多个源对象具有具有相同标识符的属性的情况。

这是working example

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

【讨论】:

  • 我用这个函数来合并两个json。但是reultant json以'0'为前缀。示例 0:{kye:值}。请帮助我如何使用我自己的字符串而不是'0'作为前缀?
  • 投了反对票,因为这是人们,尤其是新手,应该被引导到经过测试的库的情况之一。
  • @James 我是一个反应新手。您的解决方案说它需要 3 个参数,其中一个是预期的扩展。请建议我需要做出哪些改变。
  • @vinny 请不要使用这个;为什么这仍然被标记为正确答案?
【解决方案2】:

Underscore's extend 是实现这一目标的最简单快捷的方法,就像 James 评论的那样。

下面是一个使用下划线的例子:

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

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

object 1 将获取object2 的属性并返回并分配给目标。 你也可以这样做,这取决于你是否介意 object1 被修改:

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

【讨论】:

  • 谢谢。但是如果可以的话,也想避免在 node.js 中使用下划线。
  • 我只有一个轻量级的 node.js 应用,只有 express 和 mailjs。如果我只使用一个函数,就不想加载其他库。不过,你的想法仍然很酷。谢谢。
  • 注意,下划线的扩展只在第一级。它不能合并子主题。
【解决方案3】:

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

  • 使用 JSON.stringify(object) 将每个 JSON 转换为字符串。
  • 使用 + 运算符连接所有 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。是的,它会起作用的。这是非常简单的正则表达式 /}{/,无需担心字符串操作。 :-)
  • 不幸的是,object2 = {} 不起作用,因为要解析的最终字符是 ,}。可以通过添加解决,替换后:.replace(/,}^/, '}')
  • 使用任意数量的参数,不管gist.github.com/rxaviers/6734630是否为空
  • Props to @RafaelXavier 他的要点将这个答案变成了一个可用的函数。
【解决方案4】:

我看到这个帖子太旧了,但我把我的答案放在这里只是为了记录。

在您提到您想使用的上述 cmets 之一中 项目中的“express”,其中包含“connect”库 依赖列表。实际上“connect.utils”库包含一个“合并” 可以解决问题的方法。所以你可以使用第 3 方 无需添加任何新的 3rd 方库即可实现。

【讨论】:

    【解决方案5】:

    使用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
    

    【讨论】:

    • 太棒了!感谢分享。
    【解决方案6】:

    如果使用 Node 版本 >= 4,请使用 Object.assign()(请参阅 Ricardo Nolde's answer)。

    如果使用 Node 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;
    };
    

    【讨论】:

    【解决方案7】:

    以下代码将帮助您合并两个具有嵌套对象的 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;
    }
    

    【讨论】:

    • 这是唯一正确、独立的答案
    • 谢谢! @lurscher
    【解决方案8】:

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

    【讨论】:

    • 准确地说:Extendify 不是由 Node.js 开发的。它是 Node.js 的一个包。
    【解决方案9】:

    你也可以使用这个名为absorb的轻量级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' }
    

    您也可以使用它来进行克隆或仅传输源对象中不存在的值,如何执行此操作在提供的链接中进行了详细说明。

    【讨论】:

      【解决方案10】:

      你应该使用“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 say so的人:

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


      更新:

      您可以使用spread operator

      由于 version 8.6,可以在 Node.js 中原生使用 spread operator。示例如下:

      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 不适用于 0.X 版本的 Node.js。如果您正在使用其中一个版本(您现在真的不应该),您可以使用require("util")._extend,如上面的 Node.js 链接所示——有关更多详细信息,请查看 @987654329 @。

      【讨论】:

      • +1 对于任何来这里寻找原生 浏览器 替代品的人,请注意这是 ES6 功能,因此not well supported yet
      • 添加到Boaz 评论,在上面Object.assign 的Mozilla 链接中,您可以找到在浏览器中运行良好的polyfill。
      • 使用空的第一个参数调用它以避免意外损坏您的对象:var obj = Object.assign({}, o1, o2, o3)
      【解决方案11】:

      object1object2 为两个JSON 对象。

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

      这将简单地将object2 附加到object1

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

      【讨论】:

      • 这不是 OP 要求的。您将展示如何构建 JSON 对象数组。 OP 要求一种方法将来自多个 JSON 对象的键:值对组合成一个对象。
      【解决方案12】:

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

      【讨论】:

        【解决方案13】:

        使用 Object.assign() 方法可以轻松完成 -

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

        现在 object3 是 { name: 'John', location: 'San Jose' }

        【讨论】:

        • 在您的示例中,object1 也被修改。 Check my answer 了解更多详情。
        【解决方案14】:

        你可以使用 Lodash

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

        【讨论】:

          【解决方案15】:

          为了不改变目标,从正确的解决方案中获得更好的方法:

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

          【讨论】:

            【解决方案16】:

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

            【讨论】:

              【解决方案17】:

              您可以内联执行此操作,而无需像这样更改任何变量:

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

              【讨论】:

                【解决方案18】:

                使用扩展运算符。从 8.6 版本开始在 Node 中支持它

                const object1 = {name: "John"};
                const object2 = {location: "San Jose"};
                
                const obj = {...object1, ...object2}
                
                console.log(obj)
                //   {
                //     "name": "John",
                //     "location": "San Jose"
                //   }

                【讨论】:

                • 您好 Khaled,您应该尝试解释点差运算符的作用,因为这将改善您的帖子。解释远比仅仅陈述代码要好得多。它也是已经发布的答案的副本。
                猜你喜欢
                • 2012-09-16
                • 2011-06-06
                • 1970-01-01
                • 2016-10-06
                • 1970-01-01
                • 2019-07-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多