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

Asked
Active3 hr before
Viewed126 times

8 Answers

90%

The JSON.stringify() just converts a JavaScript value to a JSON string. It`s ok to use it with some primitives like Numbers, Strings or Booleans.,As you can see, you can just lose unsupported some data when copying your object in such a way. Moreover, JavaScript won`t even warn you about that, because calling JSON.stringify() with such data types does not throw any error.,(sorry for the spoiler, but that string was JSON.parse(JSON.stringify()) ),But sometimes, JSON.stringify() is a little bit… unpredictable. For instance, something like this seems to be weird:

The JSON.stringify() just converts a JavaScript value to a JSON string. It`s ok to use it with some primitives like Numbers, Strings or Booleans.

JSON.parse(JSON.stringify({
   a: 1,
   b: "Hello, world",
   c: true
})) // it`s OK
load more v
88%

Thanks for contributing an answer to Stack Overflow!,After attempting several implementations for deep comparison and copying for JSON-serializable objects, I've noticed the fastest often are just:,As long as the key-value pairs are always in the same order, yes, you can use stringify to compare using the deep equals operator (===).,Asking for help, clarification, or responding to other answers.

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}"
load more v
72%

After attempting several implementations for deep comparison and copying for JSON-serializable objects, I've noticed the fastest often are just:,As long as the key-value pairs are always in the same order, yes, you can use stringify to compare using the deep equals operator (===).,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.,If they are entered in the same order, this approach would work most of the time, but it would not be reliable.

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);
};
load more v
65%

Is it fine to use JSON.stringify for deep comparisons and cloning?, Dispose with using C# - full implementation C# | 4 months ago , Is it possible to use argsort in descending order? Python | 3 months ago , gharlan/propel-event-dispatcher-bundle Documentation PHP | 2 months ago

1.2.JSON.stringify(NaN) === JSON.stringify(null) 3. // => true4.5.JSON.stringify(Infinity) === JSON.stringify(null)6.// => true7.8.// or, to put it all together:9.JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }) === JSON.stringify({ val1: NaN, val2: null, val3: null })10.// => true11.12.// and here's the same example with "cloning" rather than comparison:13.JSON.parse(JSON.stringify({ val1: (1 / 0), val2: parseInt("hi there"), val3: NaN }))14.// => Object {val1: null, val2: null, val3: null}15.
75%

let clone = Object.assign({}, objToClone);
load more v
40%

Deep Clone using External Libraries,Alfredo Salzillo : I'd like you to note that there are some differences between deepClone and JSON.stringify/parse.,Community InputObject.assign vs SpreadDeep Clone using External LibrariesMore Ways using JavaScript,Object.assign vs Spread

const food = {
   beef: 'πŸ₯©',
   bacon: 'πŸ₯“'
}

// "Spread"
{
   ...food
}

// "Object.assign"
Object.assign({}, food)

// "JSON"
JSON.parse(JSON.stringify(food))

// RESULT:
// { beef: 'πŸ₯©', bacon: 'πŸ₯“' }
load more v
22%

The short answer to how to clone objects is simply to use Object.assign({}, obj), for a shallow copy and JSON.parse(JSON.stringify(obj)) for a deep clone of the object.,We can then make a shallow copy with the spread operator as follows:,It is also important to know the difference between shallow and deep clone (See below) to choose the best method.,If you only need to clone an object that does not contain other branches, such as functions, objects or arrays, I recommend using Object.assign().

Here is the deepClone method:

const deepClone = obj => {
   // If it's not an array or an object, returns null
   if (typeof obj !== 'object' || obj === null) {
      return obj;
   }

   let cloned, i;

   // Handle: Date
   if (obj instanceof Date) {
      cloned = new Date(obj.getTime());
      return cloned;
   }

   // Handle: array
   if (obj instanceof Array) {
      let l;
      cloned = [];
      for (i = 0, l = obj.length; i < l; i++) {
         cloned[i] = deepClone(obj[i]);
      }

      return cloned;
   }

   // Handle: object
   cloned = {};
   for (i in obj)
      if (obj.hasOwnProperty(i)) {
         cloned[i] = deepClone(obj[i]);
      }

   return cloned;
}

const obj = {
   "name": "Ricardo Metring",
   "subobj": {
      "color": "black"
   }
};
const obj2 = deepClone(obj);
load more v
60%

Note that this method will not work if your object contains: Dates, functions, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays or other complex types.

// our base object
var obj = {
   a: "hello",
   c: "test",
   po: 33,
   arr: [1, 2, 3, 4],
   anotherObj: {
      a: 33,
      str: "whazzup"
   }
};
load more v

Other "undefined-undefined" queries related to "Is it fine to use JSON.stringify for deep comparisons and cloning?"