Skip to content

Commit

Permalink
Added options.replacer for custom object serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
kapetan authored and James Halliday committed May 27, 2014
1 parent 9ad5deb commit ccf5e63
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 6 deletions.
23 changes: 17 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = function (obj, opts) {
var space = opts.space || '';
if (typeof space === 'number') space = Array(space+1).join(' ');
var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
var replacer = opts.replacer || function(key, value) { return value; };

var cmp = opts.cmp && (function (f) {
return function (node) {
Expand All @@ -18,27 +19,33 @@ module.exports = function (obj, opts) {
})(opts.cmp);

var seen = [];
return (function stringify (node, level) {
return (function stringify (parent, key, node, level) {
var indent = space ? ('\n' + new Array(level + 1).join(space)) : '';
var colonSeparator = space ? ': ' : ':';

if (node && node.toJSON && typeof node.toJSON === 'function') {
node = node.toJSON();
}

node = replacer.call(parent, key, node);

if (node === undefined) {
return;
}
if (typeof node !== 'object' || node === null) {
return json.stringify(node);
}
if (isArray(node)) {
var out = [];
for (var i = 0; i < node.length; i++) {
var item = stringify(node[i], level+1);
var item = stringify(node, i, node[i], level+1) || json.stringify(null);
out.push(indent + space + item);
}
return '[' + out.join(',') + indent + ']';
}
else {
if (seen.indexOf(node) !== -1) {
if (cycles) return stringify('__cycle__');
if (cycles) return json.stringify('__cycle__');
throw new TypeError('Converting circular structure to JSON');
}
else seen.push(node);
Expand All @@ -47,15 +54,19 @@ module.exports = function (obj, opts) {
var out = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var keyValue = stringify(key,0)
var value = stringify(node, key, node[key], level+1);

if(!value) continue;

var keyValue = json.stringify(key)
+ colonSeparator
+ stringify(node[key],level+1)
+ value;
;
out.push(indent + space + keyValue);
}
return '{' + out.join(',') + indent + '}';
}
})(obj, 0);
})({ '': obj }, '', obj, 0);
};

var isArray = Array.isArray || function (x) {
Expand Down
74 changes: 74 additions & 0 deletions test/replacer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
var test = require('tape');
var stringify = require('../');

test('replace root', function (t) {
t.plan(1);

var obj = { a: 1, b: 2, c: false };
var replacer = function(key, value) { return 'one'; };

t.equal(stringify(obj, { replacer: replacer }), '"one"');
});

test('replace numbers', function (t) {
t.plan(1);

var obj = { a: 1, b: 2, c: false };
var replacer = function(key, value) {
if(value === 1) return 'one';
if(value === 2) return 'two';
return value;
};

t.equal(stringify(obj, { replacer: replacer }), '{"a":"one","b":"two","c":false}');
});

test('replace with object', function (t) {
t.plan(1);

var obj = { a: 1, b: 2, c: false };
var replacer = function(key, value) {
if(key === 'b') return { d: 1 };
if(value === 1) return 'one';
return value;
};

t.equal(stringify(obj, { replacer: replacer }), '{"a":"one","b":{"d":"one"},"c":false}');
});

test('replace with undefined', function (t) {
t.plan(1);

var obj = { a: 1, b: 2, c: false };
var replacer = function(key, value) {
if(value === false) return;
return value;
};

t.equal(stringify(obj, { replacer: replacer }), '{"a":1,"b":2}');
});

test('replace with array', function (t) {
t.plan(1);

var obj = { a: 1, b: 2, c: false };
var replacer = function(key, value) {
if(key === 'b') return ['one', 'two'];
return value;
};

t.equal(stringify(obj, { replacer: replacer }), '{"a":1,"b":["one","two"],"c":false}');
});

test('replace array item', function (t) {
t.plan(1);

var obj = { a: 1, b: 2, c: [1,2] };
var replacer = function(key, value) {
if(value === 1) return 'one';
if(value === 2) return 'two';
return value;
};

t.equal(stringify(obj, { replacer: replacer }), '{"a":"one","b":"two","c":["one","two"]}');
});
24 changes: 24 additions & 0 deletions test/str.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,27 @@ test('simple object', function (t) {
var obj = { c: 6, b: [4,5], a: 3, z: null };
t.equal(stringify(obj), '{"a":3,"b":[4,5],"c":6,"z":null}');
});

test('object with undefined', function (t) {
t.plan(1);
var obj = { a: 3, z: undefined };
t.equal(stringify(obj), '{"a":3}');
});

test('array with undefined', function (t) {
t.plan(1);
var obj = [4, undefined, 6];
t.equal(stringify(obj), '[4,null,6]');
});

test('object with empty string', function (t) {
t.plan(1);
var obj = { a: 3, z: '' };
t.equal(stringify(obj), '{"a":3,"z":""}');
});

test('array with empty string', function (t) {
t.plan(1);
var obj = [4, '', 6];
t.equal(stringify(obj), '[4,"",6]');
});

0 comments on commit ccf5e63

Please sign in to comment.