index.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. module.exports = function (obj, opts) {
  2. if (!opts) opts = {};
  3. if (typeof opts === 'function') opts = { cmp: opts };
  4. var space = opts.space || '';
  5. if (typeof space === 'number') space = Array(space+1).join(' ');
  6. var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
  7. var replacer = opts.replacer || function(key, value) { return value; };
  8. var cmp = opts.cmp && (function (f) {
  9. return function (node) {
  10. return function (a, b) {
  11. var aobj = { key: a, value: node[a] };
  12. var bobj = { key: b, value: node[b] };
  13. return f(aobj, bobj);
  14. };
  15. };
  16. })(opts.cmp);
  17. var seen = [];
  18. return (function stringify (parent, key, node, level) {
  19. var indent = space ? ('\n' + new Array(level + 1).join(space)) : '';
  20. var colonSeparator = space ? ': ' : ':';
  21. if (node && node.toJSON && typeof node.toJSON === 'function') {
  22. node = node.toJSON();
  23. }
  24. node = replacer.call(parent, key, node);
  25. if (node === undefined) {
  26. return;
  27. }
  28. if (typeof node !== 'object' || node === null) {
  29. return JSON.stringify(node);
  30. }
  31. if (isArray(node)) {
  32. var out = [];
  33. for (var i = 0; i < node.length; i++) {
  34. var item = stringify(node, i, node[i], level+1) || JSON.stringify(null);
  35. out.push(indent + space + item);
  36. }
  37. return '[' + out.join(',') + indent + ']';
  38. }
  39. else {
  40. if (seen.indexOf(node) !== -1) {
  41. if (cycles) return JSON.stringify('__cycle__');
  42. throw new TypeError('Converting circular structure to JSON');
  43. }
  44. else seen.push(node);
  45. var keys = objectKeys(node).sort(cmp && cmp(node));
  46. var out = [];
  47. for (var i = 0; i < keys.length; i++) {
  48. var key = keys[i];
  49. var value = stringify(node, key, node[key], level+1);
  50. if(!value) continue;
  51. var keyValue = JSON.stringify(key)
  52. + colonSeparator
  53. + value;
  54. ;
  55. out.push(indent + space + keyValue);
  56. }
  57. seen.splice(seen.indexOf(node), 1);
  58. return '{' + out.join(',') + indent + '}';
  59. }
  60. })({ '': obj }, '', obj, 0);
  61. };
  62. var isArray = Array.isArray || function (x) {
  63. return {}.toString.call(x) === '[object Array]';
  64. };
  65. var objectKeys = Object.keys || function (obj) {
  66. var has = Object.prototype.hasOwnProperty || function () { return true };
  67. var keys = [];
  68. for (var key in obj) {
  69. if (has.call(obj, key)) keys.push(key);
  70. }
  71. return keys;
  72. };