Skip to content

Commit b04febd

Browse files
Ivan Zverevljharb
Ivan Zverev
authored andcommitted
[New] parse: add allowSparse option for collapsing arrays with missing indices
Fixes #181.
1 parent b522d2e commit b04febd

File tree

4 files changed

+32
-0
lines changed

4 files changed

+32
-0
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,13 @@ var noSparse = qs.parse('a[1]=b&a[15]=c');
227227
assert.deepEqual(noSparse, { a: ['b', 'c'] });
228228
```
229229

230+
You may also use `allowSparse` option to parse sparse arrays:
231+
232+
```javascript
233+
var sparseArray = qs.parse('a[1]=2&a[3]=5', { allowSparse: true });
234+
assert.deepEqual(sparseArray, { a: [, '2', , '5'] });
235+
```
236+
230237
Note that an empty string is also a value, and will be preserved:
231238

232239
```javascript

lib/parse.js

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ var isArray = Array.isArray;
88
var defaults = {
99
allowDots: false,
1010
allowPrototypes: false,
11+
allowSparse: false,
1112
arrayLimit: 20,
1213
charset: 'utf-8',
1314
charsetSentinel: false,
@@ -217,6 +218,7 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
217218
return {
218219
allowDots: typeof opts.allowDots === 'undefined' ? defaults.allowDots : !!opts.allowDots,
219220
allowPrototypes: typeof opts.allowPrototypes === 'boolean' ? opts.allowPrototypes : defaults.allowPrototypes,
221+
allowSparse: typeof opts.allowSparse === 'boolean' ? opts.allowSparse : defaults.allowSparse,
220222
arrayLimit: typeof opts.arrayLimit === 'number' ? opts.arrayLimit : defaults.arrayLimit,
221223
charset: charset,
222224
charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
@@ -253,5 +255,9 @@ module.exports = function (str, opts) {
253255
obj = utils.merge(obj, newObj, options);
254256
}
255257

258+
if (options.allowSparse === true) {
259+
return obj;
260+
}
261+
256262
return utils.compact(obj);
257263
};

test/parse.js

+9
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,15 @@ test('parse()', function (t) {
269269
st.end();
270270
});
271271

272+
t.test('parses sparse arrays', function (st) {
273+
/* eslint no-sparse-arrays: 0 */
274+
st.deepEqual(qs.parse('a[4]=1&a[1]=2', { allowSparse: true }), { a: [, '2', , , '1'] });
275+
st.deepEqual(qs.parse('a[1][b][2][c]=1', { allowSparse: true }), { a: [, { b: [, , { c: '1' }] }] });
276+
st.deepEqual(qs.parse('a[1][2][3][c]=1', { allowSparse: true }), { a: [, [, , [, , , { c: '1' }]]] });
277+
st.deepEqual(qs.parse('a[1][2][3][c][1]=1', { allowSparse: true }), { a: [, [, , [, , , { c: [, '1'] }]]] });
278+
st.end();
279+
});
280+
272281
t.test('parses semi-parsed strings', function (st) {
273282
st.deepEqual(qs.parse({ 'a[b]': 'c' }), { a: { b: 'c' } });
274283
st.deepEqual(qs.parse({ 'a[b]': 'c', 'a[d]': 'e' }), { a: { b: 'c', d: 'e' } });

test/stringify.js

+10
Original file line numberDiff line numberDiff line change
@@ -789,5 +789,15 @@ test('stringify()', function (t) {
789789
st.end();
790790
});
791791

792+
t.test('stringifies sparse arrays', function (st) {
793+
/* eslint no-sparse-arrays: 0 */
794+
st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true }), 'a[1]=2&a[4]=1');
795+
st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true }), 'a[1][b][2][c]=1');
796+
st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true }), 'a[1][2][3][c]=1');
797+
st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true }), 'a[1][2][3][c][1]=1');
798+
799+
st.end();
800+
});
801+
792802
t.end();
793803
});

0 commit comments

Comments
 (0)