【问题标题】:Determining the equality of JSON-formatted objects in node.js确定 node.js 中 JSON 格式对象的相等性
【发布时间】:2012-03-23 21:09:04
【问题描述】:

在 node.js 中比较两个 JSON 格式的对象数据最有效的方法是什么?

这些对象不包含“未定义”或函数,它们的原型是Object

听说 node.js 中的 JSON 有很好的支持

【问题讨论】:

  • 什么是“JSON”?什么样的比较?
  • JSON 是一个由字符串、数字、布尔值、日期、数组和其他 json 组成的对象。数组也可以包含 JSONSs
  • @Dan:错了;那是一个对象。 JSON 是一种格式。
  • 我明白了;你的意思是 POJO(普通的旧 Javascript 对象)
  • 我建议JSON.stringify(x) === JSON.stringify(y)

标签: json node.js


【解决方案1】:

朋友们!如果我不明白某些事情,或者用错误的术语解释问题,我真的很抱歉。我想做的就是比较两条 JSON 标准化 数据的相等性,如下所示:

{"skip":0, "limit":7, "arr": [1682, 439, {"x":2, arr:[]}] }

{"skip":0, "limit":7, "arr": [1682, 450, "a", ["something"] }

我 100% 确定在这些数据中不会有 Datenullundefined 等函数。我想说我不想在最一般的情况下比较 JavaScript 对象(复杂的原型、循环链接和所有这些东西)。这些数据的原型是Object。我也确信很多熟练的程序员在我之前已经回答了这个问题。

我缺少的主要是我不知道如何正确解释我的问题。请随时编辑我的帖子。

我的回答:

第一种方式:效率低但可靠。您可以修改a generic method like this,这样就不会浪费时间寻找函数和undefined。请注意,泛型方法对对象进行了三次迭代(里面有三个for .. in循环)

第二种方式:高效但有一个限制。我发现JSON.stringifynode.js 中速度非常快。最快的解决方案是:

JSON.stringify(data1) == JSON.stringify(data2)

非常重要的说明! 据我所知,JavaScript 和 JSON 都与对象字段的顺序无关。但是,如果您比较由对象组成的字符串,这将非常重要。在我的程序中,对象字段始终以相同的顺序创建,因此上面的代码有效。我没有在 V8 文档中搜索,但我认为我们可以依赖字段创建顺序。在其他情况下,请注意使用此方法。

在我的具体情况下,第二种方法的效率是第一种方法的 10 倍。

【讨论】:

  • 但是第二种方式可靠吗?我听说这种方法是有争议的,因为 javascript 不保留属性的顺序,而您的解决方案取决于它。
  • @juzerali。你说的很对,我应该据此编辑我的答案
【解决方案2】:

我对各种技术进行了一些基准测试,下划线排在首位:

> node nodeCompare.js 

deep comparison res: true took: 418 (underscore)
hash comparison res: true took: 933
assert compare  res: true took: 2025
string compare  res: true took: 1679

这里是源代码:

var _ = require('underscore');

var assert = require('assert');

var crypto = require('crypto');

var large = require('./large.json');

var large2 = JSON.parse(JSON.stringify(large));

var t1 = new Date();
var hash = crypto.createHash('md5').update(JSON.stringify(large)).digest('hex');
var t2 = new Date();

var res = _.isEqual(large, large2);

var t3 = new Date();

var res2 = (hash == crypto.createHash('md5').update(JSON.stringify(large2)).digest('hex'));

var t4 = new Date();

assert.deepEqual(large, large2);

var t5 = new Date();

var res4 = JSON.stringify(large) === JSON.stringify(large2);

var t6 = new Date();

console.log("deep comparison res: "+res+" took: "+ (t3.getTime() - t2.getTime()));
console.log("hash comparison res: "+res2+" took: "+ (t4.getTime() - t3.getTime()));
console.log("assert compare  res: true took: "+ (t5.getTime() - t4.getTime()));
console.log("string compare  res: "+res4+" took: "+ (t6.getTime() - t5.getTime()));

【讨论】:

  • 对于 {a:1,b:1}{b:1,a:1} json 对象,您的哈希和字符串比较将(有时?)返回 false(不相等),其他方法将(始终)返回 true(相等)。
【解决方案3】:

从表面上看,我相信这就是您正在寻找的:

Object Comparison in JavaScript

不过,更完整的答案可以在这里找到:

How do you determine equality for two JavaScript objects?

这些答案分别来自 2 年前和 3 年前。在发布之前在网站上搜索您想要的问题总是一个好主意,或者更广泛地搜索 Google —— Google 中的“javascript 比较两个 JSON 对象”返回很多。目前,前 4 名都是 StackOverflow 的答案。

【讨论】:

    【解决方案4】:

    您可以对 JSON 对象使用重命名/取消设置/设置差异 - https://github.com/mirek/node-rus-diff

    npm install rus-diff
    

    您的示例 JSON 对象:

    a = {"skip":0, "limit":7, "arr": [1682, 439, {"x":2, arr:[]}] }
    b = {"skip":0, "limit":7, "arr": [1682, 450, "a", ["something"]] }
    
    var rusDiff = require('rus-diff').rusDiff
    
    console.log(rusDiff(a, b))
    

    ...生成以下差异:

    { '$set': { 'arr.1': 450, 'arr.2': 'a', 'arr.3': [ 'something' ] } }
    

    ...这是 MongoDB 兼容的差异格式。

    如果文档相同,rusDiff(a, b) 返回false

    【讨论】:

      猜你喜欢
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多