diff --git a/.eslintrc b/.eslintrc index 9e7a211a..a9343fa6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -15,7 +15,7 @@ "indent": [2, 4], "max-lines-per-function": [2, { "max": 150 }], "max-params": [2, 15], - "max-statements": [2, 52], + "max-statements": [2, 53], "multiline-comment-style": 0, "no-continue": 1, "no-magic-numbers": 0, diff --git a/lib/stringify.js b/lib/stringify.js index 5ace512e..55c37404 100644 --- a/lib/stringify.js +++ b/lib/stringify.js @@ -126,7 +126,7 @@ var stringify = function stringify( for (var i = 0; i < valuesArray.length; ++i) { valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format)); } - return [formatter(keyValue) + (i === 1 ? '[]' : '') + '=' + valuesJoined]; + return [formatter(keyValue) + (isArray(obj) && valuesArray.length === 1 ? '[]' : '') + '=' + valuesJoined]; } return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))]; } @@ -150,6 +150,8 @@ var stringify = function stringify( objKeys = sort ? keys.sort(sort) : keys; } + var adjustedPrefix = generateArrayPrefix === 'comma' && isArray(obj) && obj.length === 1 ? prefix + '[]' : prefix; + for (var j = 0; j < objKeys.length; ++j) { var key = objKeys[j]; var value = typeof key === 'object' && typeof key.value !== 'undefined' ? key.value : obj[key]; @@ -159,8 +161,8 @@ var stringify = function stringify( } var keyPrefix = isArray(obj) - ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix - : prefix + (allowDots ? '.' + key : '[' + key + ']'); + ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, key) : adjustedPrefix + : adjustedPrefix + (allowDots ? '.' + key : '[' + key + ']'); sideChannel.set(object, step); var valueSideChannel = getSideChannel(); diff --git a/test/stringify.js b/test/stringify.js index f1ff112e..fda52413 100644 --- a/test/stringify.js +++ b/test/stringify.js @@ -132,15 +132,32 @@ test('stringify()', function (t) { }); t.test('stringifies an array value with one item vs multiple items', function (st) { - st.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c'); - st.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c'); - st.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a[]=c'); // so it parses back as an array - st.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true }), 'a[0]=c'); + st.test('non-array item', function (s2t) { + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=c'); + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=c'); + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c'); + s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true }), 'a=c'); - st.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c&a[1]=d'); - st.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c&a[]=d'); - st.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c,d'); - st.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true }), 'a[0]=c&a[1]=d'); + s2t.end(); + }); + + st.test('array with a single item', function (s2t) { + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c'); + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c'); + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a[]=c'); // so it parses back as an array + s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true }), 'a[0]=c'); + + s2t.end(); + }); + + st.test('array with multiple items', function (s2t) { + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c&a[1]=d'); + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c&a[]=d'); + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c,d'); + s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true }), 'a[0]=c&a[1]=d'); + + s2t.end(); + }); st.end(); }); @@ -362,12 +379,12 @@ test('stringify()', function (t) { st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices' }), 'b[0]=&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets' }), 'b[]=&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat' }), 'b=&c=c'); - st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma' }), 'b=&c=c'); + st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma' }), 'b[]=&c=c'); // with strictNullHandling st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', strictNullHandling: true }), 'b[0]&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', strictNullHandling: true }), 'b[]&c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat', strictNullHandling: true }), 'b&c=c'); - st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true }), 'b&c=c'); + st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true }), 'b[]&c=c'); // with skipNulls st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', skipNulls: true }), 'c=c'); st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', skipNulls: true }), 'c=c'); @@ -695,7 +712,7 @@ test('stringify()', function (t) { arrayFormat: 'comma' } ), - 'a=' + date.getTime(), + 'a%5B%5D=' + date.getTime(), 'works with arrayFormat comma' );