Dan
Dan

Reputation: 57921

Determining the equality of JSON-formatted objects in node.js

What is the most efficient way to compare two JSON-formatted objects data in node.js?

These objects do not contain "undefined" or functions and their propotype is Object.

I've heard there is a good support if JSON in node.js

Upvotes: 9

Views: 31603

Answers (4)

Rene Wooller
Rene Wooller

Reputation: 1147

I've done some benchmarking of the various techniques, with underscore coming out on top:

> 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

Here is the source code:

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

Upvotes: 4

Mirek Rusin
Mirek Rusin

Reputation: 19472

You can use rename/unset/set diff for JSON objects - https://github.com/mirek/node-rus-diff

npm install rus-diff

Your example JSON objects:

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

...generate the following diff:

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

...which is MongoDB compatible diff format.

If documents are the same, rusDiff(a, b) returns false.

Upvotes: 1

Dan
Dan

Reputation: 57921

Friends! I'm really sorry if I don't understand something, or explain question in wrong terms. All I wanna do is to compare the equality of two pieces of JSON-standardized data like this:

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

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

I'm 100% sure there will be no functions, Date, null or undefined, etc. in these data. I want to say I don't want to compare JavaScript objects in the most general case (with complex prototypes, circular links and all this stuff). The prototype of these data will be Object. I'm also sure lots of skillful programmers have answered this question before me.

The main thing I'm missing is that I don't know how to explain my question correctly. Please feel free to edit my post.

My answer:

First way: Unefficient but reliable. You can modify a generic method like this so it does not waste time looking for functions and undefined. Please note that generic method iterates the objects three times (there are three for .. in loops inside)

Second way: Efficient but has one restriction. I've found JSON.stringify is extremely fast in node.js. The fastest solution that works is:

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

Very important note! As far as I know, neither JavaScript nor JSON don't matter the order of the object fields. However, if you compare strings made of objects, this will matter much. In my program the object fields are always created in the same order, so the code above works. I didn't search in the V8 documentation, but I think we can rely on the fields creation order. In other case, be aware of using this method.

In my concrete case the second way is 10 times more efficient then the first way.

Upvotes: 8

DreadPirateShawn
DreadPirateShawn

Reputation: 8412

On the face of it, I believe this is what you're looking for:

Object Comparison in JavaScript

However, the more complete answer is found here:

How do you determine equality for two JavaScript objects?

These answers are from 2 and 3 years ago, respectively. It's always a good idea to search the site for your intended question before posting, or search Google more broadly -- "javascript compare two JSON objects" in Google returns a lot. The top 4 hits are all StackOverflow answers, at the moment.

Upvotes: 2

Related Questions