Skip to content

Commit

Permalink
Add a filter option.
Browse files Browse the repository at this point in the history
This matches `JSON.stringify()`, which accepts a filter function or
property list as its second argument. If a function is specified, it
is called to obtain the replacement value. Otherwise, if an array is
specified, it is used to select properties and array indices for
stringification.
  • Loading branch information
Kit Cambridge committed May 21, 2015
1 parent 2df097b commit 391a7c3
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 7 deletions.
28 changes: 21 additions & 7 deletions lib/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ var internals = {
};


internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHandling) {
internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHandling, filter) {

if (Utils.isBuffer(obj)) {
if (typeof filter === 'function') {
obj = filter(prefix, obj);
}
else if (Utils.isBuffer(obj)) {
obj = obj.toString();
}
else if (obj instanceof Date) {
Expand All @@ -54,15 +57,15 @@ internals.stringify = function (obj, prefix, generateArrayPrefix, strictNullHand
return values;
}

var objKeys = Object.keys(obj);
var objKeys = Array.isArray(filter) ? filter : Object.keys(obj);
for (var i = 0, il = objKeys.length; i < il; ++i) {
var key = objKeys[i];

if (Array.isArray(obj)) {
values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling));
values = values.concat(internals.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, filter));
}
else {
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling));
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix, strictNullHandling, filter));
}
}

Expand All @@ -75,6 +78,15 @@ module.exports = function (obj, options) {
options = options || {};
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : internals.strictNullHandling;
var objKeys;
var filter;
if (typeof options.filter === 'function') {
filter = options.filter;
obj = filter('', obj);
}
else if (Array.isArray(options.filter)) {
objKeys = filter = options.filter;
}

var keys = [];

Expand All @@ -97,10 +109,12 @@ module.exports = function (obj, options) {

var generateArrayPrefix = internals.arrayPrefixGenerators[arrayFormat];

var objKeys = Object.keys(obj);
if (!objKeys) {
objKeys = Object.keys(obj);
}
for (var i = 0, il = objKeys.length; i < il; ++i) {
var key = objKeys[i];
keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling));
keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix, strictNullHandling, filter));
}

return keys.join(delimiter);
Expand Down
36 changes: 36 additions & 0 deletions test/stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,40 @@ describe('stringify()', function () {
global.Buffer = tempBuffer;
done();
});

it('selects properties when filter=array', function (done) {

expect(Qs.stringify({ a: 'b' }, { filter: ['a'] })).to.equal('a=b');
expect(Qs.stringify({ a: 1}, { filter: [] })).to.equal('');
expect(Qs.stringify({ a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' }, { filter: ['a', 'b', 0, 2]})).to.equal('a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3');
done();

});

it('supports custom representations when filter=function', function (done) {

var calls = 0;
var obj = { a: 'b', c: 'd', e: { f: new Date(1257894000000) } };
var filterFunc = function (prefix, value) {

calls++;
if (calls === 1) {
expect(prefix).to.be.empty();
expect(value).to.equal(obj);
}
else if (prefix === 'c') {
return;
}
else if (value instanceof Date) {
expect(prefix).to.equal('e[f]');
return value.getTime();
}
return value;
};

expect(Qs.stringify(obj, { filter: filterFunc })).to.equal('a=b&e%5Bf%5D=1257894000000');
expect(calls).to.equal(5);
done();

});
});

0 comments on commit 391a7c3

Please sign in to comment.