u2nc8w
Last Updated: February 25, 2016
·
3.368K
· jetheis
06ce0320e3f7aa0e0c36c54fbe463c6e

Deterministic JSON.stringify()

Using JavaScript objects as generic maps can be difficult, especially if you want to use objects as keys, because map keys are required to be (or are converted to) strings. Objects can be converted to strings using JSON.stringify(), but the ordering of keys is not guaranteed here, which means the same (or equivalent) objects can result in different strings.

These functions provide a way to serialize and deserialize objects deterministically by converting them to key-value pairs, sorting those pairs by key, then passing them through JSON.stringify(). This code requires Underscore.js.

Stringify:

function stringify(obj) {
  function flatten(obj) {
    if (_.isObject(obj)) {
      return _.sortBy(_.map(
          _.pairs(obj),
          function(p) { return [p[0], flatten(p[1])]; }
        ),
        function(p) { return p[0]; }
      );
    }
    return obj;
  }
  return JSON.stringify(flatten(obj));
}

Parse:

function parse(str) {
  function inflate(obj, pairs) {
     _.each(pairs, function(p) {
      obj[p[0]] = _.isArray(p[1]) ?
        inflate({}, p[1]) :
        p[1];
    });
    return obj;
  }
  return inflate({}, JSON.parse(str));
}