Projekt

Obecné

Profil

Stáhnout (17.8 KB) Statistiky
| Větev: | Revize:
1
# qs <sup>[![Version Badge][2]][1]</sup>
2

    
3
[![Build Status][3]][4]
4
[![dependency status][5]][6]
5
[![dev dependency status][7]][8]
6
[![License][license-image]][license-url]
7
[![Downloads][downloads-image]][downloads-url]
8

    
9
[![npm badge][11]][1]
10

    
11
A querystring parsing and stringifying library with some added security.
12

    
13
Lead Maintainer: [Jordan Harband](https://github.com/ljharb)
14

    
15
The **qs** module was originally created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring).
16

    
17
## Usage
18

    
19
```javascript
20
var qs = require('qs');
21
var assert = require('assert');
22

    
23
var obj = qs.parse('a=c');
24
assert.deepEqual(obj, { a: 'c' });
25

    
26
var str = qs.stringify(obj);
27
assert.equal(str, 'a=c');
28
```
29

    
30
### Parsing Objects
31

    
32
[](#preventEval)
33
```javascript
34
qs.parse(string, [options]);
35
```
36

    
37
**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
38
For example, the string `'foo[bar]=baz'` converts to:
39

    
40
```javascript
41
assert.deepEqual(qs.parse('foo[bar]=baz'), {
42
    foo: {
43
        bar: 'baz'
44
    }
45
});
46
```
47

    
48
When using the `plainObjects` option the parsed value is returned as a null object, created via `Object.create(null)` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like:
49

    
50
```javascript
51
var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
52
assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
53
```
54

    
55
By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties. *WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten. Always be careful with this option.
56

    
57
```javascript
58
var protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
59
assert.deepEqual(protoObject, { a: { hasOwnProperty: 'b' } });
60
```
61

    
62
URI encoded strings work too:
63

    
64
```javascript
65
assert.deepEqual(qs.parse('a%5Bb%5D=c'), {
66
    a: { b: 'c' }
67
});
68
```
69

    
70
You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`:
71

    
72
```javascript
73
assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
74
    foo: {
75
        bar: {
76
            baz: 'foobarbaz'
77
        }
78
    }
79
});
80
```
81

    
82
By default, when nesting objects **qs** will only parse up to 5 children deep. This means if you attempt to parse a string like
83
`'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
84

    
85
```javascript
86
var expected = {
87
    a: {
88
        b: {
89
            c: {
90
                d: {
91
                    e: {
92
                        f: {
93
                            '[g][h][i]': 'j'
94
                        }
95
                    }
96
                }
97
            }
98
        }
99
    }
100
};
101
var string = 'a[b][c][d][e][f][g][h][i]=j';
102
assert.deepEqual(qs.parse(string), expected);
103
```
104

    
105
This depth can be overridden by passing a `depth` option to `qs.parse(string, [options])`:
106

    
107
```javascript
108
var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
109
assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
110
```
111

    
112
The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number.
113

    
114
For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option:
115

    
116
```javascript
117
var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
118
assert.deepEqual(limited, { a: 'b' });
119
```
120

    
121
To bypass the leading question mark, use `ignoreQueryPrefix`:
122

    
123
```javascript
124
var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });
125
assert.deepEqual(prefixed, { a: 'b', c: 'd' });
126
```
127

    
128
An optional delimiter can also be passed:
129

    
130
```javascript
131
var delimited = qs.parse('a=b;c=d', { delimiter: ';' });
132
assert.deepEqual(delimited, { a: 'b', c: 'd' });
133
```
134

    
135
Delimiters can be a regular expression too:
136

    
137
```javascript
138
var regexed = qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ });
139
assert.deepEqual(regexed, { a: 'b', c: 'd', e: 'f' });
140
```
141

    
142
Option `allowDots` can be used to enable dot notation:
143

    
144
```javascript
145
var withDots = qs.parse('a.b=c', { allowDots: true });
146
assert.deepEqual(withDots, { a: { b: 'c' } });
147
```
148

    
149
If you have to deal with legacy browsers or services, there's
150
also support for decoding percent-encoded octets as iso-8859-1:
151

    
152
```javascript
153
var oldCharset = qs.parse('a=%A7', { charset: 'iso-8859-1' });
154
assert.deepEqual(oldCharset, { a: '§' });
155
```
156

    
157
Some services add an initial `utf8=✓` value to forms so that old
158
Internet Explorer versions are more likely to submit the form as
159
utf-8. Additionally, the server can check the value against wrong
160
encodings of the checkmark character and detect that a query string
161
or `application/x-www-form-urlencoded` body was *not* sent as
162
utf-8, eg. if the form had an `accept-charset` parameter or the
163
containing page had a different character set.
164

    
165
**qs** supports this mechanism via the `charsetSentinel` option.
166
If specified, the `utf8` parameter will be omitted from the
167
returned object. It will be used to switch to `iso-8859-1`/`utf-8`
168
mode depending on how the checkmark is encoded.
169

    
170
**Important**: When you specify both the `charset` option and the
171
`charsetSentinel` option, the `charset` will be overridden when
172
the request contains a `utf8` parameter from which the actual
173
charset can be deduced. In that sense the `charset` will behave
174
as the default charset rather than the authoritative charset.
175

    
176
```javascript
177
var detectedAsUtf8 = qs.parse('utf8=%E2%9C%93&a=%C3%B8', {
178
    charset: 'iso-8859-1',
179
    charsetSentinel: true
180
});
181
assert.deepEqual(detectedAsUtf8, { a: 'ø' });
182

    
183
// Browsers encode the checkmark as &#10003; when submitting as iso-8859-1:
184
var detectedAsIso8859_1 = qs.parse('utf8=%26%2310003%3B&a=%F8', {
185
    charset: 'utf-8',
186
    charsetSentinel: true
187
});
188
assert.deepEqual(detectedAsIso8859_1, { a: 'ø' });
189
```
190

    
191
If you want to decode the `&#...;` syntax to the actual character,
192
you can specify the `interpretNumericEntities` option as well:
193

    
194
```javascript
195
var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', {
196
    charset: 'iso-8859-1',
197
    interpretNumericEntities: true
198
});
199
assert.deepEqual(detectedAsIso8859_1, { a: '' });
200
```
201

    
202
It also works when the charset has been detected in `charsetSentinel`
203
mode.
204

    
205
### Parsing Arrays
206

    
207
**qs** can also parse arrays using a similar `[]` notation:
208

    
209
```javascript
210
var withArray = qs.parse('a[]=b&a[]=c');
211
assert.deepEqual(withArray, { a: ['b', 'c'] });
212
```
213

    
214
You may specify an index as well:
215

    
216
```javascript
217
var withIndexes = qs.parse('a[1]=c&a[0]=b');
218
assert.deepEqual(withIndexes, { a: ['b', 'c'] });
219
```
220

    
221
Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number
222
to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving
223
their order:
224

    
225
```javascript
226
var noSparse = qs.parse('a[1]=b&a[15]=c');
227
assert.deepEqual(noSparse, { a: ['b', 'c'] });
228
```
229

    
230
Note that an empty string is also a value, and will be preserved:
231

    
232
```javascript
233
var withEmptyString = qs.parse('a[]=&a[]=b');
234
assert.deepEqual(withEmptyString, { a: ['', 'b'] });
235

    
236
var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
237
assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
238
```
239

    
240
**qs** will also limit specifying indices in an array to a maximum index of `20`. Any array members with an index of greater than `20` will
241
instead be converted to an object with the index as the key. This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
242

    
243
```javascript
244
var withMaxIndex = qs.parse('a[100]=b');
245
assert.deepEqual(withMaxIndex, { a: { '100': 'b' } });
246
```
247

    
248
This limit can be overridden by passing an `arrayLimit` option:
249

    
250
```javascript
251
var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
252
assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
253
```
254

    
255
To disable array parsing entirely, set `parseArrays` to `false`.
256

    
257
```javascript
258
var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
259
assert.deepEqual(noParsingArrays, { a: { '0': 'b' } });
260
```
261

    
262
If you mix notations, **qs** will merge the two items into an object:
263

    
264
```javascript
265
var mixedNotation = qs.parse('a[0]=b&a[b]=c');
266
assert.deepEqual(mixedNotation, { a: { '0': 'b', b: 'c' } });
267
```
268

    
269
You can also create arrays of objects:
270

    
271
```javascript
272
var arraysOfObjects = qs.parse('a[][b]=c');
273
assert.deepEqual(arraysOfObjects, { a: [{ b: 'c' }] });
274
```
275

    
276
Some people use comma to join array, **qs** can parse it:
277
```javascript
278
var arraysOfObjects = qs.parse('a=b,c', { comma: true })
279
assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] })
280
```
281
(_this cannot convert nested objects, such as `a={b:1},{c:d}`_)
282

    
283
### Stringifying
284

    
285
[](#preventEval)
286
```javascript
287
qs.stringify(object, [options]);
288
```
289

    
290
When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
291

    
292
```javascript
293
assert.equal(qs.stringify({ a: 'b' }), 'a=b');
294
assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
295
```
296

    
297
This encoding can be disabled by setting the `encode` option to `false`:
298

    
299
```javascript
300
var unencoded = qs.stringify({ a: { b: 'c' } }, { encode: false });
301
assert.equal(unencoded, 'a[b]=c');
302
```
303

    
304
Encoding can be disabled for keys by setting the `encodeValuesOnly` option to `true`:
305
```javascript
306
var encodedValues = qs.stringify(
307
    { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
308
    { encodeValuesOnly: true }
309
);
310
assert.equal(encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h');
311
```
312

    
313
This encoding can also be replaced by a custom encoding method set as `encoder` option:
314

    
315
```javascript
316
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) {
317
    // Passed in values `a`, `b`, `c`
318
    return // Return encoded string
319
}})
320
```
321

    
322
_(Note: the `encoder` option does not apply if `encode` is `false`)_
323

    
324
Analogue to the `encoder` there is a `decoder` option for `parse` to override decoding of properties and values:
325

    
326
```javascript
327
var decoded = qs.parse('x=z', { decoder: function (str) {
328
    // Passed in values `x`, `z`
329
    return // Return decoded string
330
}})
331
```
332

    
333
Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage.
334

    
335
When arrays are stringified, by default they are given explicit indices:
336

    
337
```javascript
338
qs.stringify({ a: ['b', 'c', 'd'] });
339
// 'a[0]=b&a[1]=c&a[2]=d'
340
```
341

    
342
You may override this by setting the `indices` option to `false`:
343

    
344
```javascript
345
qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
346
// 'a=b&a=c&a=d'
347
```
348

    
349
You may use the `arrayFormat` option to specify the format of the output array:
350

    
351
```javascript
352
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
353
// 'a[0]=b&a[1]=c'
354
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
355
// 'a[]=b&a[]=c'
356
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
357
// 'a=b&a=c'
358
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
359
// 'a=b,c'
360
```
361

    
362
When objects are stringified, by default they use bracket notation:
363

    
364
```javascript
365
qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
366
// 'a[b][c]=d&a[b][e]=f'
367
```
368

    
369
You may override this to use dot notation by setting the `allowDots` option to `true`:
370

    
371
```javascript
372
qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
373
// 'a.b.c=d&a.b.e=f'
374
```
375

    
376
Empty strings and null values will omit the value, but the equals sign (=) remains in place:
377

    
378
```javascript
379
assert.equal(qs.stringify({ a: '' }), 'a=');
380
```
381

    
382
Key with no values (such as an empty object or array) will return nothing:
383

    
384
```javascript
385
assert.equal(qs.stringify({ a: [] }), '');
386
assert.equal(qs.stringify({ a: {} }), '');
387
assert.equal(qs.stringify({ a: [{}] }), '');
388
assert.equal(qs.stringify({ a: { b: []} }), '');
389
assert.equal(qs.stringify({ a: { b: {}} }), '');
390
```
391

    
392
Properties that are set to `undefined` will be omitted entirely:
393

    
394
```javascript
395
assert.equal(qs.stringify({ a: null, b: undefined }), 'a=');
396
```
397

    
398
The query string may optionally be prepended with a question mark:
399

    
400
```javascript
401
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
402
```
403

    
404
The delimiter may be overridden with stringify as well:
405

    
406
```javascript
407
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
408
```
409

    
410
If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
411

    
412
```javascript
413
var date = new Date(7);
414
assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
415
assert.equal(
416
    qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
417
    'a=7'
418
);
419
```
420

    
421
You may use the `sort` option to affect the order of parameter keys:
422

    
423
```javascript
424
function alphabeticalSort(a, b) {
425
    return a.localeCompare(b);
426
}
427
assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
428
```
429

    
430
Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
431
If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you
432
pass an array, it will be used to select properties and array indices for stringification:
433

    
434
```javascript
435
function filterFunc(prefix, value) {
436
    if (prefix == 'b') {
437
        // Return an `undefined` value to omit a property.
438
        return;
439
    }
440
    if (prefix == 'e[f]') {
441
        return value.getTime();
442
    }
443
    if (prefix == 'e[g][0]') {
444
        return value * 2;
445
    }
446
    return value;
447
}
448
qs.stringify({ a: 'b', c: 'd', e: { f: new Date(123), g: [2] } }, { filter: filterFunc });
449
// 'a=b&c=d&e[f]=123&e[g][0]=4'
450
qs.stringify({ a: 'b', c: 'd', e: 'f' }, { filter: ['a', 'e'] });
451
// 'a=b&e=f'
452
qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] });
453
// 'a[0]=b&a[2]=d'
454
```
455

    
456
### Handling of `null` values
457

    
458
By default, `null` values are treated like empty strings:
459

    
460
```javascript
461
var withNull = qs.stringify({ a: null, b: '' });
462
assert.equal(withNull, 'a=&b=');
463
```
464

    
465
Parsing does not distinguish between parameters with and without equal signs. Both are converted to empty strings.
466

    
467
```javascript
468
var equalsInsensitive = qs.parse('a&b=');
469
assert.deepEqual(equalsInsensitive, { a: '', b: '' });
470
```
471

    
472
To distinguish between `null` values and empty strings use the `strictNullHandling` flag. In the result string the `null`
473
values have no `=` sign:
474

    
475
```javascript
476
var strictNull = qs.stringify({ a: null, b: '' }, { strictNullHandling: true });
477
assert.equal(strictNull, 'a&b=');
478
```
479

    
480
To parse values without `=` back to `null` use the `strictNullHandling` flag:
481

    
482
```javascript
483
var parsedStrictNull = qs.parse('a&b=', { strictNullHandling: true });
484
assert.deepEqual(parsedStrictNull, { a: null, b: '' });
485
```
486

    
487
To completely skip rendering keys with `null` values, use the `skipNulls` flag:
488

    
489
```javascript
490
var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true });
491
assert.equal(nullsSkipped, 'a=b');
492
```
493

    
494
If you're communicating with legacy systems, you can switch to `iso-8859-1`
495
using the `charset` option:
496

    
497
```javascript
498
var iso = qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' });
499
assert.equal(iso, '%E6=%E6');
500
```
501

    
502
Characters that don't exist in `iso-8859-1` will be converted to numeric
503
entities, similar to what browsers do:
504

    
505
```javascript
506
var numeric = qs.stringify({ a: '' }, { charset: 'iso-8859-1' });
507
assert.equal(numeric, 'a=%26%239786%3B');
508
```
509

    
510
You can use the `charsetSentinel` option to announce the character by
511
including an `utf8=✓` parameter with the proper encoding if the checkmark,
512
similar to what Ruby on Rails and others do when submitting forms.
513

    
514
```javascript
515
var sentinel = qs.stringify({ a: '' }, { charsetSentinel: true });
516
assert.equal(sentinel, 'utf8=%E2%9C%93&a=%E2%98%BA');
517

    
518
var isoSentinel = qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' });
519
assert.equal(isoSentinel, 'utf8=%26%2310003%3B&a=%E6');
520
```
521

    
522
### Dealing with special character sets
523

    
524
By default the encoding and decoding of characters is done in `utf-8`,
525
and `iso-8859-1` support is also built in via the `charset` parameter.
526

    
527
If you wish to encode querystrings to a different character set (i.e.
528
[Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the
529
[`qs-iconv`](https://github.com/martinheidegger/qs-iconv) library:
530

    
531
```javascript
532
var encoder = require('qs-iconv/encoder')('shift_jis');
533
var shiftJISEncoded = qs.stringify({ a: 'こんにちは!' }, { encoder: encoder });
534
assert.equal(shiftJISEncoded, 'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I');
535
```
536

    
537
This also works for decoding of query strings:
538

    
539
```javascript
540
var decoder = require('qs-iconv/decoder')('shift_jis');
541
var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
542
assert.deepEqual(obj, { a: 'こんにちは!' });
543
```
544

    
545
### RFC 3986 and RFC 1738 space encoding
546

    
547
RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
548
In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
549

    
550
```
551
assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
552
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
553
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
554
```
555

    
556
[1]: https://npmjs.org/package/qs
557
[2]: http://versionbadg.es/ljharb/qs.svg
558
[3]: https://api.travis-ci.org/ljharb/qs.svg
559
[4]: https://travis-ci.org/ljharb/qs
560
[5]: https://david-dm.org/ljharb/qs.svg
561
[6]: https://david-dm.org/ljharb/qs
562
[7]: https://david-dm.org/ljharb/qs/dev-status.svg
563
[8]: https://david-dm.org/ljharb/qs?type=dev
564
[9]: https://ci.testling.com/ljharb/qs.png
565
[10]: https://ci.testling.com/ljharb/qs
566
[11]: https://nodei.co/npm/qs.png?downloads=true&stars=true
567
[license-image]: http://img.shields.io/npm/l/qs.svg
568
[license-url]: LICENSE
569
[downloads-image]: http://img.shields.io/npm/dm/qs.svg
570
[downloads-url]: http://npm-stat.com/charts.html?package=qs
(6-6/7)