README.md (14636B)
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 ### Parsing Arrays 150 151 **qs** can also parse arrays using a similar `[]` notation: 152 153 ```javascript 154 var withArray = qs.parse('a[]=b&a[]=c'); 155 assert.deepEqual(withArray, { a: ['b', 'c'] }); 156 ``` 157 158 You may specify an index as well: 159 160 ```javascript 161 var withIndexes = qs.parse('a[1]=c&a[0]=b'); 162 assert.deepEqual(withIndexes, { a: ['b', 'c'] }); 163 ``` 164 165 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 166 to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving 167 their order: 168 169 ```javascript 170 var noSparse = qs.parse('a[1]=b&a[15]=c'); 171 assert.deepEqual(noSparse, { a: ['b', 'c'] }); 172 ``` 173 174 Note that an empty string is also a value, and will be preserved: 175 176 ```javascript 177 var withEmptyString = qs.parse('a[]=&a[]=b'); 178 assert.deepEqual(withEmptyString, { a: ['', 'b'] }); 179 180 var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c'); 181 assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] }); 182 ``` 183 184 **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 185 instead be converted to an object with the index as the key: 186 187 ```javascript 188 var withMaxIndex = qs.parse('a[100]=b'); 189 assert.deepEqual(withMaxIndex, { a: { '100': 'b' } }); 190 ``` 191 192 This limit can be overridden by passing an `arrayLimit` option: 193 194 ```javascript 195 var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 }); 196 assert.deepEqual(withArrayLimit, { a: { '1': 'b' } }); 197 ``` 198 199 To disable array parsing entirely, set `parseArrays` to `false`. 200 201 ```javascript 202 var noParsingArrays = qs.parse('a[]=b', { parseArrays: false }); 203 assert.deepEqual(noParsingArrays, { a: { '0': 'b' } }); 204 ``` 205 206 If you mix notations, **qs** will merge the two items into an object: 207 208 ```javascript 209 var mixedNotation = qs.parse('a[0]=b&a[b]=c'); 210 assert.deepEqual(mixedNotation, { a: { '0': 'b', b: 'c' } }); 211 ``` 212 213 You can also create arrays of objects: 214 215 ```javascript 216 var arraysOfObjects = qs.parse('a[][b]=c'); 217 assert.deepEqual(arraysOfObjects, { a: [{ b: 'c' }] }); 218 ``` 219 220 ### Stringifying 221 222 [](#preventEval) 223 ```javascript 224 qs.stringify(object, [options]); 225 ``` 226 227 When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect: 228 229 ```javascript 230 assert.equal(qs.stringify({ a: 'b' }), 'a=b'); 231 assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c'); 232 ``` 233 234 This encoding can be disabled by setting the `encode` option to `false`: 235 236 ```javascript 237 var unencoded = qs.stringify({ a: { b: 'c' } }, { encode: false }); 238 assert.equal(unencoded, 'a[b]=c'); 239 ``` 240 241 Encoding can be disabled for keys by setting the `encodeValuesOnly` option to `true`: 242 ```javascript 243 var encodedValues = qs.stringify( 244 { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, 245 { encodeValuesOnly: true } 246 ); 247 assert.equal(encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h'); 248 ``` 249 250 This encoding can also be replaced by a custom encoding method set as `encoder` option: 251 252 ```javascript 253 var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) { 254 // Passed in values `a`, `b`, `c` 255 return // Return encoded string 256 }}) 257 ``` 258 259 _(Note: the `encoder` option does not apply if `encode` is `false`)_ 260 261 Analogue to the `encoder` there is a `decoder` option for `parse` to override decoding of properties and values: 262 263 ```javascript 264 var decoded = qs.parse('x=z', { decoder: function (str) { 265 // Passed in values `x`, `z` 266 return // Return decoded string 267 }}) 268 ``` 269 270 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. 271 272 When arrays are stringified, by default they are given explicit indices: 273 274 ```javascript 275 qs.stringify({ a: ['b', 'c', 'd'] }); 276 // 'a[0]=b&a[1]=c&a[2]=d' 277 ``` 278 279 You may override this by setting the `indices` option to `false`: 280 281 ```javascript 282 qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }); 283 // 'a=b&a=c&a=d' 284 ``` 285 286 You may use the `arrayFormat` option to specify the format of the output array: 287 288 ```javascript 289 qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) 290 // 'a[0]=b&a[1]=c' 291 qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) 292 // 'a[]=b&a[]=c' 293 qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) 294 // 'a=b&a=c' 295 ``` 296 297 When objects are stringified, by default they use bracket notation: 298 299 ```javascript 300 qs.stringify({ a: { b: { c: 'd', e: 'f' } } }); 301 // 'a[b][c]=d&a[b][e]=f' 302 ``` 303 304 You may override this to use dot notation by setting the `allowDots` option to `true`: 305 306 ```javascript 307 qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true }); 308 // 'a.b.c=d&a.b.e=f' 309 ``` 310 311 Empty strings and null values will omit the value, but the equals sign (=) remains in place: 312 313 ```javascript 314 assert.equal(qs.stringify({ a: '' }), 'a='); 315 ``` 316 317 Key with no values (such as an empty object or array) will return nothing: 318 319 ```javascript 320 assert.equal(qs.stringify({ a: [] }), ''); 321 assert.equal(qs.stringify({ a: {} }), ''); 322 assert.equal(qs.stringify({ a: [{}] }), ''); 323 assert.equal(qs.stringify({ a: { b: []} }), ''); 324 assert.equal(qs.stringify({ a: { b: {}} }), ''); 325 ``` 326 327 Properties that are set to `undefined` will be omitted entirely: 328 329 ```javascript 330 assert.equal(qs.stringify({ a: null, b: undefined }), 'a='); 331 ``` 332 333 The query string may optionally be prepended with a question mark: 334 335 ```javascript 336 assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d'); 337 ``` 338 339 The delimiter may be overridden with stringify as well: 340 341 ```javascript 342 assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d'); 343 ``` 344 345 If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option: 346 347 ```javascript 348 var date = new Date(7); 349 assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A')); 350 assert.equal( 351 qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }), 352 'a=7' 353 ); 354 ``` 355 356 You may use the `sort` option to affect the order of parameter keys: 357 358 ```javascript 359 function alphabeticalSort(a, b) { 360 return a.localeCompare(b); 361 } 362 assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y'); 363 ``` 364 365 Finally, you can use the `filter` option to restrict which keys will be included in the stringified output. 366 If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you 367 pass an array, it will be used to select properties and array indices for stringification: 368 369 ```javascript 370 function filterFunc(prefix, value) { 371 if (prefix == 'b') { 372 // Return an `undefined` value to omit a property. 373 return; 374 } 375 if (prefix == 'e[f]') { 376 return value.getTime(); 377 } 378 if (prefix == 'e[g][0]') { 379 return value * 2; 380 } 381 return value; 382 } 383 qs.stringify({ a: 'b', c: 'd', e: { f: new Date(123), g: [2] } }, { filter: filterFunc }); 384 // 'a=b&c=d&e[f]=123&e[g][0]=4' 385 qs.stringify({ a: 'b', c: 'd', e: 'f' }, { filter: ['a', 'e'] }); 386 // 'a=b&e=f' 387 qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] }); 388 // 'a[0]=b&a[2]=d' 389 ``` 390 391 ### Handling of `null` values 392 393 By default, `null` values are treated like empty strings: 394 395 ```javascript 396 var withNull = qs.stringify({ a: null, b: '' }); 397 assert.equal(withNull, 'a=&b='); 398 ``` 399 400 Parsing does not distinguish between parameters with and without equal signs. Both are converted to empty strings. 401 402 ```javascript 403 var equalsInsensitive = qs.parse('a&b='); 404 assert.deepEqual(equalsInsensitive, { a: '', b: '' }); 405 ``` 406 407 To distinguish between `null` values and empty strings use the `strictNullHandling` flag. In the result string the `null` 408 values have no `=` sign: 409 410 ```javascript 411 var strictNull = qs.stringify({ a: null, b: '' }, { strictNullHandling: true }); 412 assert.equal(strictNull, 'a&b='); 413 ``` 414 415 To parse values without `=` back to `null` use the `strictNullHandling` flag: 416 417 ```javascript 418 var parsedStrictNull = qs.parse('a&b=', { strictNullHandling: true }); 419 assert.deepEqual(parsedStrictNull, { a: null, b: '' }); 420 ``` 421 422 To completely skip rendering keys with `null` values, use the `skipNulls` flag: 423 424 ```javascript 425 var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true }); 426 assert.equal(nullsSkipped, 'a=b'); 427 ``` 428 429 ### Dealing with special character sets 430 431 By default the encoding and decoding of characters is done in `utf-8`. If you 432 wish to encode querystrings to a different character set (i.e. 433 [Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the 434 [`qs-iconv`](https://github.com/martinheidegger/qs-iconv) library: 435 436 ```javascript 437 var encoder = require('qs-iconv/encoder')('shift_jis'); 438 var shiftJISEncoded = qs.stringify({ a: 'こんにちは!' }, { encoder: encoder }); 439 assert.equal(shiftJISEncoded, 'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I'); 440 ``` 441 442 This also works for decoding of query strings: 443 444 ```javascript 445 var decoder = require('qs-iconv/decoder')('shift_jis'); 446 var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder }); 447 assert.deepEqual(obj, { a: 'こんにちは!' }); 448 ``` 449 450 ### RFC 3986 and RFC 1738 space encoding 451 452 RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible. 453 In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'. 454 455 ``` 456 assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c'); 457 assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c'); 458 assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c'); 459 ``` 460 461 [1]: https://npmjs.org/package/qs 462 [2]: http://versionbadg.es/ljharb/qs.svg 463 [3]: https://api.travis-ci.org/ljharb/qs.svg 464 [4]: https://travis-ci.org/ljharb/qs 465 [5]: https://david-dm.org/ljharb/qs.svg 466 [6]: https://david-dm.org/ljharb/qs 467 [7]: https://david-dm.org/ljharb/qs/dev-status.svg 468 [8]: https://david-dm.org/ljharb/qs?type=dev 469 [9]: https://ci.testling.com/ljharb/qs.png 470 [10]: https://ci.testling.com/ljharb/qs 471 [11]: https://nodei.co/npm/qs.png?downloads=true&stars=true 472 [license-image]: http://img.shields.io/npm/l/qs.svg 473 [license-url]: LICENSE 474 [downloads-image]: http://img.shields.io/npm/dm/qs.svg 475 [downloads-url]: http://npm-stat.com/charts.html?package=qs