Skip to content

Commit f7be831

Browse files
yaodingydsindresorhus
authored andcommitted
Add parseNumbers option to .parse() (#171)
1 parent 5295243 commit f7be831

File tree

5 files changed

+60
-10
lines changed

5 files changed

+60
-10
lines changed

index.d.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@ export interface ParseOptions {
1313
*
1414
*
1515
* queryString.parse('foo[]=1&foo[]=2&foo[]=3', {arrayFormat: 'bracket'});
16-
* //=> foo: [1, 2, 3]
16+
* //=> foo: ['1', '2', '3']
1717
*
1818
* - `index`: Parse arrays with index representation:
1919
*
2020
*
2121
* queryString.parse('foo[0]=1&foo[1]=2&foo[3]=3', {arrayFormat: 'index'});
22-
* //=> foo: [1, 2, 3]
22+
* //=> foo: ['1', '2', '3']
2323
*
2424
* - `comma`: Parse arrays with elements separated by comma:
2525
*
2626
*
2727
* queryString.parse('foo=1,2,3', {arrayFormat: 'comma'});
28-
* //=> foo: [1, 2, 3]
28+
* //=> foo: ['1', '2', '3']
2929
*
3030
* - `none`: Parse arrays with elements using duplicate keys:
3131
*
3232
*
3333
* queryString.parse('foo=1&foo=2&foo=3');
34-
* //=> foo: [1, 2, 3]
34+
* //=> foo: ['1', '2', '3']
3535
*/
3636
readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'none';
3737

@@ -55,10 +55,21 @@ export interface ParseOptions {
5555
*/
5656
readonly sort?: ((itemLeft: string, itemRight: string) => number) | false;
5757

58+
/**
59+
* Parse the value as a number type instead of string type if it's a number.
60+
*
61+
* @default false
62+
*
63+
* @example
64+
*
65+
* queryString.parse('foo[]=1&foo[]=2&foo[]=3', {parseNumbers: true});
66+
* //=> foo: [1, 2, 3]
67+
*/
68+
readonly parseNumbers?: boolean;
5869
}
5970

6071
export interface ParsedQuery {
61-
readonly [key: string]: string | string[] | null | undefined;
72+
readonly [key: string]: string | number | Array<string | number> | null | undefined;
6273
}
6374

6475
/**

index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ function parse(input, options) {
175175
options = Object.assign({
176176
decode: true,
177177
sort: true,
178-
arrayFormat: 'none'
178+
arrayFormat: 'none',
179+
parseNumbers: false
179180
}, options);
180181

181182
const formatter = parserForArrayFormat(options);
@@ -200,6 +201,10 @@ function parse(input, options) {
200201
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
201202
value = value === undefined ? null : decode(value, options);
202203

204+
if (options.parseNumbers && !Number.isNaN(Number(value))) {
205+
value = Number(value);
206+
}
207+
203208
formatter(decode(key, options), value, ret);
204209
}
205210

index.test-d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ expectType<queryString.ParsedQuery>(
5151
expectType<queryString.ParsedQuery>(
5252
queryString.parse('?foo=bar', {arrayFormat: 'comma'})
5353
);
54+
expectType<queryString.ParsedQuery>(
55+
queryString.parse('?foo=1', {parseNumbers: true})
56+
);
5457

5558
// Parse URL
5659
expectType<queryString.ParsedUrl>(queryString.parseUrl('?foo=bar'));
@@ -70,6 +73,9 @@ expectType<queryString.ParsedUrl>(
7073
expectType<queryString.ParsedUrl>(
7174
queryString.parseUrl('?foo=bar', {arrayFormat: 'comma'})
7275
);
76+
expectType<queryString.ParsedQuery>(
77+
queryString.parse('?foo=1', {parseNumbers: true})
78+
);
7379

7480
// Extract
7581
expectType<string>(queryString.extract('http://foo.bar/?abc=def&hij=klm'));

readme.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,28 +72,28 @@ Default: `'none'`
7272

7373
```js
7474
queryString.parse('foo[]=1&foo[]=2&foo[]=3', {arrayFormat: 'bracket'});
75-
//=> foo: [1, 2, 3]
75+
//=> foo: ['1', '2', '3']
7676
```
7777

7878
- `'index'`: Parse arrays with index representation:
7979

8080
```js
8181
queryString.parse('foo[0]=1&foo[1]=2&foo[3]=3', {arrayFormat: 'index'});
82-
//=> foo: [1, 2, 3]
82+
//=> foo: ['1', '2', '3']
8383
```
8484

8585
- `'comma'`: Parse arrays with elements separated by comma:
8686

8787
```js
8888
queryString.parse('foo=1,2,3', {arrayFormat: 'comma'});
89-
//=> foo: [1, 2, 3]
89+
//=> foo: ['1', '2', '3']
9090
```
9191

9292
- `'none'`: Parse arrays with elements using duplicate keys:
9393

9494
```js
9595
queryString.parse('foo=1&foo=2&foo=3');
96-
//=> foo: [1, 2, 3]
96+
//=> foo: ['1', '2', '3']
9797
```
9898

9999
##### sort
@@ -103,6 +103,18 @@ Default: `true`
103103

104104
Supports both `Function` as a custom sorting function or `false` to disable sorting.
105105

106+
##### parseNumbers
107+
108+
Type: `boolean`<br>
109+
Default: `false`
110+
111+
```js
112+
queryString.parse('foo[]=1&foo[]=2&foo[]=3', {parseNumbers: true});
113+
//=> foo: [1, 2, 3]
114+
```
115+
116+
Parse the value as a number type instead of string type if it's a number.
117+
106118
### .stringify(object, [options])
107119

108120
Stringify an object into a query string and sorting the keys.

test/parse.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,19 @@ test('decode keys and values', t => {
228228
test('disable decoding of keys and values', t => {
229229
t.deepEqual(queryString.parse('tags=postal%20office,burger%2C%20fries%20and%20coke', {decode: false}), {tags: 'postal%20office,burger%2C%20fries%20and%20coke'});
230230
});
231+
232+
test('number value returns as string by default', t => {
233+
t.deepEqual(queryString.parse('foo=1'), {foo: '1'});
234+
});
235+
236+
test('number value returns as number if option is set', t => {
237+
t.deepEqual(queryString.parse('foo=1', {parseNumbers: true}), {foo: 1});
238+
t.deepEqual(queryString.parse('foo=12.3&bar=123e-1', {parseNumbers: true}), {foo: 12.3, bar: 12.3});
239+
t.deepEqual(queryString.parse('foo=0x11&bar=12.00', {parseNumbers: true}), {foo: 17, bar: 12});
240+
});
241+
242+
test('NaN value returns as string if option is set', t => {
243+
t.deepEqual(queryString.parse('foo=null', {parseNumbers: true}), {foo: 'null'});
244+
t.deepEqual(queryString.parse('foo=undefined', {parseNumbers: true}), {foo: 'undefined'});
245+
t.deepEqual(queryString.parse('foo=100a&bar=100', {parseNumbers: true}), {foo: '100a', bar: 100});
246+
});

0 commit comments

Comments
 (0)