Skip to content

Commit

Permalink
Add arrayFormat option
Browse files Browse the repository at this point in the history
The arrayFormat option recognizes 3 values: brackets, indices, and
repeat. It defaults to bracket.

See the comments in #46
  • Loading branch information
mjackson committed Feb 17, 2015
1 parent 9250c4c commit b84d9ad
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 20 deletions.
33 changes: 24 additions & 9 deletions lib/stringify.js
Expand Up @@ -7,11 +7,21 @@ var Utils = require('./utils');

var internals = {
delimiter: '&',
indices: true
arrayPrefixGenerators: {
brackets: function (prefix, key) {
return prefix + '[]';
},
indices: function (prefix, key) {
return prefix + '[' + key + ']';
},
repeat: function (prefix, key) {
return prefix;
}
}
};


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

if (Utils.isBuffer(obj)) {
obj = obj.toString();
Expand Down Expand Up @@ -39,13 +49,11 @@ internals.stringify = function (obj, prefix, options) {
var objKeys = Object.keys(obj);
for (var i = 0, il = objKeys.length; i < il; ++i) {
var key = objKeys[i];
if (!options.indices &&
Array.isArray(obj)) {

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

Expand All @@ -57,7 +65,6 @@ module.exports = function (obj, options) {

options = options || {};
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter;
options.indices = typeof options.indices === 'boolean' ? options.indices : internals.indices;

var keys = [];

Expand All @@ -67,10 +74,18 @@ module.exports = function (obj, options) {
return '';
}

var generateArrayPrefix;
if (options.arrayFormat in internals.arrayPrefixGenerators) {
generateArrayPrefix = internals.arrayPrefixGenerators[options.arrayFormat];
}
else {
generateArrayPrefix = internals.arrayPrefixGenerators.brackets;
}

var 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, options));
keys = keys.concat(internals.stringify(obj[key], key, generateArrayPrefix));
}

return keys.join(delimiter);
Expand Down
28 changes: 17 additions & 11 deletions test/stringify.js
Expand Up @@ -36,34 +36,40 @@ describe('stringify()', function () {
done();
});

it('stringifies an array value', function (done) {
it('uses bracket notation when arrayFormat is not specified', function (done) {

expect(Qs.stringify({ a: ['b', 'c', 'd'] })).to.equal('a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d');
expect(Qs.stringify({ a: ['b', 'c', 'd'] })).to.equal('a%5B%5D=b&a%5B%5D=c&a%5B%5D=d');
done();
});

it('omits array indices when asked', function (done) {
it('uses bracket notation when arrayFormat=brackets', function (done) {

expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false })).to.equal('a=b&a=c&a=d');
expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'brackets' })).to.equal('a%5B%5D=b&a%5B%5D=c&a%5B%5D=d');
done();
});

it('stringifies a nested array value', function (done) {
it('uses index notation when arrayFormat=indices', function (done) {

expect(Qs.stringify({ a: { b: ['c', 'd'] } })).to.equal('a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d');
expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'indices' })).to.equal('a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d');
done();
});

it('stringifies an object inside an array', function (done) {
it('repeats keys when arrayFormat=repeat', function (done) {

expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'repeat' })).to.equal('a=b&a=c&a=d');
done();
});

it('stringifies a nested array value', function (done) {

expect(Qs.stringify({ a: [{ b: 'c' }] })).to.equal('a%5B0%5D%5Bb%5D=c');
expect(Qs.stringify({ a: [{ b: { c: [1] } }] })).to.equal('a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1');
expect(Qs.stringify({ a: { b: ['c', 'd'] } })).to.equal('a%5Bb%5D%5B%5D=c&a%5Bb%5D%5B%5D=d');
done();
});

it('does not omit object keys when indices = false', function (done) {
it('stringifies an object inside an array', function (done) {

expect(Qs.stringify({ a: [{ b: 'c' }] }, { indices: false })).to.equal('a%5Bb%5D=c');
expect(Qs.stringify({ a: [{ b: 'c' }] })).to.equal('a%5B%5D%5Bb%5D=c');
expect(Qs.stringify({ a: [{ b: { c: [1] } }] })).to.equal('a%5B%5D%5Bb%5D%5Bc%5D%5B%5D=1');
done();
});

Expand Down

0 comments on commit b84d9ad

Please sign in to comment.