Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it fine to use JSON.stringify for deep comparisons and cloning?

After attempting several implementations for deep comparison and copying for JSON-serializable objects, I've noticed the fastest often are just:

function deep_clone(a){
   return JSON.parse(JSON.stringify(a));
};
function is_equal(a,b){
    return JSON.stringify(a) === JSON.stringify(b);
};

I feel like this is cheating, though. Like I'll find some problem that will annoy me on future. Is it fine to use those?

like image 342
MaiaVictor Avatar asked Mar 13 '13 02:03

MaiaVictor


People also ask

When should I use JSON Stringify?

The JSON. stringify() method in Javascript is used to create a JSON string out of it. While developing an application using JavaScript, many times it is needed to serialize the data to strings for storing the data into a database or for sending the data to an API or web server.

What's the point of JSON parse JSON Stringify?

parse() function is used to convert a string into a JavaScript object while the JSON. stringify() function is used to convert a JavaScript object into a string.

Is JSON parse JSON Stringify slow?

parse: 702 ms. Clearly JSON. parse is the slowest of them, and by some margin.

Is parsing JSON safe?

Parsing JSON can be a dangerous procedure if the JSON text contains untrusted data. For example, if you parse untrusted JSON in a browser using the JavaScript “eval” function, and the untrusted JSON text itself contains JavaScript code, the code will execute during parse time.


2 Answers

JavaScript does not guarantee the order of keys.

If they are entered in the same order, this approach would work most of the time, but it would not be reliable.

Also, it would return false for objects that were deeply equal, but whose keys were entered in a different order:

JSON.stringify({ a: 1, b: 2}) === "{"a":1,"b":2}"

JSON.stringify({ b: 2, a: 1}) === "{"b":2,"a":1}"
like image 52
dstreit Avatar answered Sep 22 '22 00:09

dstreit


I realize it's an old question, but I just wanted to add a bit more to the answers, since someone might otherwise walk away from this page mistakenly thinking that using JSON.stringify for comparisons/cloning will work without issue so long as it isn't used to compare/clone objects whose members are unordered. (To be fair to the accepted answer, they shouldn't walk away thinking that; it says, "If [the members] are entered in the same order, this approach would work most of the time.")

Code probably illustrates the potential hiccups best:

JSON.stringify(NaN) === JSON.stringify(null)
// => true

JSON.stringify(Infinity) === JSON.stringify(null)
// => true

// or, to put it all together:
JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }) === JSON.stringify({ val1: NaN, val2: null, val3: null })
// => true

// and here's the same example with "cloning" rather than comparison:
JSON.parse(JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }))
// => Object {val1: null, val2: null, val3: null}

These are quirks that can cause trouble even when ordering isn't an issue (which, as others have said, it can be). It's probably not likely in most cases that these quirks will rear their ugly heads, but it's good to be aware of them, since they could result in some really hard to find bugs.

like image 41
Jason Rogers Avatar answered Sep 21 '22 00:09

Jason Rogers