Skip to content

Commit

Permalink
Make parseNumbers and parseBooleans options work with `arrayForma…
Browse files Browse the repository at this point in the history
…t` (#202)

Co-Authored-By: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
yaodingyd and sindresorhus committed Aug 14, 2019
1 parent 22b5532 commit d2451aa
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
26 changes: 20 additions & 6 deletions index.js
Expand Up @@ -171,6 +171,16 @@ function extract(input) {
return input.slice(queryStart + 1);
}

function parseValue(value, options) {
if (options.parseNumbers && !Number.isNaN(Number(value)) && (typeof value === 'string' && value.trim() !== '')) {
value = Number(value);
} else if (options.parseBooleans && value !== null && (value.toLowerCase() === 'true' || value.toLowerCase() === 'false')) {
value = value.toLowerCase() === 'true';
}

return value;
}

function parse(input, options) {
options = Object.assign({
decode: true,
Expand Down Expand Up @@ -201,14 +211,18 @@ function parse(input, options) {
// Missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
value = value === undefined ? null : decode(value, options);
formatter(decode(key, options), value, ret);
}

if (options.parseNumbers && !Number.isNaN(Number(value)) && (typeof value === 'string' && value.trim() !== '')) {
value = Number(value);
} else if (options.parseBooleans && value !== null && (value.toLowerCase() === 'true' || value.toLowerCase() === 'false')) {
value = value.toLowerCase() === 'true';
for (const key of Object.keys(ret)) {
const value = ret[key];
if (typeof value === 'object' && value !== null) {
for (const k of Object.keys(value)) {
value[k] = parseValue(value[k], options);
}
} else {
ret[key] = parseValue(value, options);
}

formatter(decode(key, options), value, ret);
}

if (options.sort === false) {
Expand Down
21 changes: 21 additions & 0 deletions test/parse.js
Expand Up @@ -246,6 +246,13 @@ test('NaN value returns as string if option is set', t => {
t.deepEqual(queryString.parse('foo= &bar=', {parseNumbers: true}), {foo: ' ', bar: ''});
});

test('parseNumbers works with arrayFormat', t => {
t.deepEqual(queryString.parse('foo[]=1&foo[]=2&foo[]=3&bar=1', {parseNumbers: true, arrayFormat: 'bracket'}), {foo: [1, 2, 3], bar: 1});
t.deepEqual(queryString.parse('foo=1,2,a', {parseNumbers: true, arrayFormat: 'comma'}), {foo: [1, 2, 'a']});
t.deepEqual(queryString.parse('foo[0]=1&foo[1]=2&foo[2]', {parseNumbers: true, arrayFormat: 'index'}), {foo: [1, 2, null]});
t.deepEqual(queryString.parse('foo=1&foo=2&foo=3', {parseNumbers: true}), {foo: [1, 2, 3]});
});

test('boolean value returns as string by default', t => {
t.deepEqual(queryString.parse('foo=true'), {foo: 'true'});
});
Expand All @@ -255,7 +262,21 @@ test('boolean value returns as boolean if option is set', t => {
t.deepEqual(queryString.parse('foo=false&bar=true', {parseBooleans: true}), {foo: false, bar: true});
});

test('parseBooleans works with arrayFormat', t => {
t.deepEqual(queryString.parse('foo[]=true&foo[]=false&foo[]=true&bar=1', {parseBooleans: true, arrayFormat: 'bracket'}), {foo: [true, false, true], bar: '1'});
t.deepEqual(queryString.parse('foo=true,false,a', {parseBooleans: true, arrayFormat: 'comma'}), {foo: [true, false, 'a']});
t.deepEqual(queryString.parse('foo[0]=true&foo[1]=false&foo[2]', {parseBooleans: true, arrayFormat: 'index'}), {foo: [true, false, null]});
t.deepEqual(queryString.parse('foo=true&foo=false&foo=3', {parseBooleans: true}), {foo: [true, false, '3']});
});

test('boolean value returns as boolean and number value as number if both options are set', t => {
t.deepEqual(queryString.parse('foo=true&bar=1.12', {parseNumbers: true, parseBooleans: true}), {foo: true, bar: 1.12});
t.deepEqual(queryString.parse('foo=16.32&bar=false', {parseNumbers: true, parseBooleans: true}), {foo: 16.32, bar: false});
});

test('parseNumbers and parseBooleans can work with arrayFormat at the same time', t => {
t.deepEqual(queryString.parse('foo=true&foo=false&bar=1.12&bar=2', {parseNumbers: true, parseBooleans: true}), {foo: [true, false], bar: [1.12, 2]});
t.deepEqual(queryString.parse('foo[]=true&foo[]=false&foo[]=true&bar[]=1&bar[]=2', {parseNumbers: true, parseBooleans: true, arrayFormat: 'bracket'}), {foo: [true, false, true], bar: [1, 2]});
t.deepEqual(queryString.parse('foo=true,false&bar=1,2', {parseNumbers: true, parseBooleans: true, arrayFormat: 'comma'}), {foo: [true, false], bar: [1, 2]});
t.deepEqual(queryString.parse('foo[0]=true&foo[1]=false&bar[0]=1&bar[1]=2', {parseNumbers: true, parseBooleans: true, arrayFormat: 'index'}), {foo: [true, false], bar: [1, 2]});
});

0 comments on commit d2451aa

Please sign in to comment.