How do I make a checksum from a JavaScript Object?

3 years later...

I came across this question as I wanted to hash my JSON objects to create Etags for my HTTP responses. So I ended up writing my own solution for Node, jsum, which boils down to a simple serializer:

/**
 * Stringifies a JSON object (not any randon JS object).
 *
 * It should be noted that JS objects can have members of
 * specific type (e.g. function), that are not supported
 * by JSON.
 *
 * @param {Object} obj JSON object
 * @returns {String} stringified JSON object.
 */
function serialize (obj) {
  if (Array.isArray(obj)) {
    return JSON.stringify(obj.map(i => serialize(i)))
  } else if (typeof obj === 'object' && obj !== null) {
    return Object.keys(obj)
      .sort()
      .map(k => `${k}:${serialize(obj[k])}`)
      .join('|')
  }

  return obj
}

You can then take the result and hash it using common algorithms (e.g. SHA256) or use the convenient method of digest from jsum package.


Please note the license here!


You can collect the keys into an array with Object.keys(), sort that array and then checksum the keys/values in that known, predictable order. I don't know of any way to use JSON.stringify() with all the sorted keys at once though so you'd have to do your own checksum.

I am not aware of any built-in method for something like this. Object keys are NOT guaranteed to be in any particular order so it would not be safe to rely on that.


If you don't have nested objects or arrays as property values, then you could do something like this:

// creates an array of alternating property name, property value
// with properties in sorted order
// then stringify's that array
function stringifyPropsInOrder(obj) {
    var keys = Object.keys(obj).sort();
    var output = [], prop;
    for (var i = 0; i < keys.length; i++) {
        prop = keys[i];
        output.push(prop);
        output.push(obj[prop]);
    }
    return JSON.stringify(output);
}

function compareObjects(a, b) {
    return stringifyPropsInOrder(a) === stringifyPropsInOrder(b);
}

If you want faster performance, you don't have to stringify (that was just done here to save code). You could just return the flattened output array and compare the arrays directly.


If you could have embedded objects as property values, then some more work has to do to recusively expand those into the same flattened array of properties/values.


You could also make a function which compares your objects in place:

function compareObjects(a, b) {
  var akeys = Object.keys(a);
  var bkeys = Object.keys(b);
  var len = akeys.length;
  if (len != bkeys.length) return false;
  for (var i = 0; i < len; i++) {
    if (a[akeys[i]] !== b[akeys[i]]) return false;
  }
  return true;
}

This assumes they are objects passed in, and that they're simple flat objects. Logic could be added to check these assumptions and recursively check if sub-objects are equal.