JSON.stringify versions (v3)

Revision 3 of this benchmark created on


Description

JSON.stringify (if avail) vs custom implementations

Setup

var shortJSON = {
      "fathers|5-10": [{
        "married|0-1": true,
        "name": "@MALE_FIRST_NAME @LAST_NAME",
        "sons": null,
        "daughters|0-3": [{
          "age|0-31": 0,
          "name": "@FEMALE_FIRST_NAME"
        }]
      }]
    };
    
    var longJSON = {
      "fathers": [{
        "married": false,
        "name": "William Martinez",
        "sons": null,
        "daughters": [{
          "age": 8,
          "name": "Michelle"
        }, {
          "age": 29,
          "name": "Donna"
        }]
      }, {
        "married": false,
        "name": "Thomas Taylor",
        "sons": null,
        "daughters": [{
          "age": 6,
          "name": "Angela"
        }]
      }, {
        "married": false,
        "name": "Christopher Johnson",
        "sons": null,
        "daughters": [{
          "age": 11,
          "name": "Laura"
        }, {
          "age": 27,
          "name": "Shirley"
        }]
      }, {
        "married": true,
        "name": "Christopher Davis",
        "sons": null,
        "daughters": [{
          "age": 17,
          "name": "Carol"
        }, {
          "age": 28,
          "name": "Michelle"
        }]
      }, {
        "married": false,
        "name": "Christopher Jackson",
        "sons": null,
        "daughters": [{
          "age": 4,
          "name": "Linda"
        }, {
          "age": 29,
          "name": "Betty"
        }]
      }, {
        "married": false,
        "name": "Michael Harris",
        "sons": null,
        "daughters": [{
          "age": 8,
          "name": "Carol"
        }, {
          "age": 26,
          "name": "Deborah"
        }, {
          "age": 14,
          "name": "Sharon"
        }]
      }]
    };
    
    var customStringify1 = function stringify(o) {
        var type = typeof o,
            tmp, k;
        var objectToString = Object.prototype.toString;
        if (type === 'string') {
          return '"' + o + '"';
        } else if (type === 'number') {
          return o;
        } else if (type === 'object') {
          tmp = objectToString.call(o);
          if (tmp === '[object Object]') {
            tmp = '{';
            for (k in o) {
              if (o.hasOwnProperty(k)) tmp += '"' + k + '":' + stringify(o[k]) + ",";
            }
            tmp = tmp.slice(0, -1) + "}";
            return tmp;
          } else if (tmp === '[object Array]') {
            k = o.length;
            while (k--) {
              o[k] = stringify(o[k]);
            }
            return '[' + o.join(',') + ']';
          } else {
            return String(o);
          }
        }
        };
    
    var customStringify2 = function(obj) {
        var t = typeof(obj);
        if (t != "object" || obj === null) {
          // simple data type
          if (t == "string") obj = '"' + obj + '"';
          return String(obj);
        } else {
          // recurse array or object
          var n, v, json = [],
              arr = (obj && obj.constructor == Array);
          for (n in obj) {
            v = obj[n];
            t = typeof(v);
            if (t == "string") v = '"' + v + '"';
            else if (t == "object" && v !== null) v = JSON.stringify(v);
            json.push((arr ? "" : '"' + n + '":') + String(v));
          }
          return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
        }
        };
    
    var processors = {
      "null": function(val) {
        if (val === null) {
          return "null";
        }
      },
      "undefined": function(val) {
        if (typeof val === 'undefined') {
          return "undefined";
        }
      },
      "string": function(val) {
        if (typeof val === 'string') {
          return "\"" + val + "\"";
        }
      },
      "boolean": function(val) {
        if (typeof val === 'boolean') {
          return String(val);
        }
      },
      "number": function(val) {
        if (typeof val === 'number') {
          return String(val);
        }
      },
      "function": function(val) {
        if (typeof val === 'function') {
          return String(val);
        }
      },
      "Array": function(val) {
        if (Array.isArray(val)) {
          return "[" + (val.map(contraStringify).join(',')) + "]";
        }
      },
      "object": function(val) {
        var contents, keys;
        if (typeof val === "object") {
          keys = Object.keys(val);
          if (!keys.length) {
            return "{}";
          }
          contents = keys.map(function(key) {
            return "\"" + key + "\":" + (contraStringify(val[key]));
          }).join(',');
          return "{" + contents + "}";
        }
      }
    };
    var contraStringify = function(val) {
        var fn, name, out;
        for (name in processors) {
          fn = processors[name];
          out = fn(val);
          if (out != null) {
            return out;
          }
        }
        };

Test runner

Ready to run.

Testing in
TestOps/sec
JSON.stringify (internal)
JSON.stringify(shortJSON);
JSON.stringify(longJSON);
ready
customStringify1
customStringify1(shortJSON);
customStringify1(longJSON);
ready
customStringify2
customStringify2(shortJSON);
customStringify2(longJSON);
ready
contraStringify
contraStringify(shortJSON);
contraStringify(longJSON);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.