You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

475 lines
14 KiB

  1. # qs <sup>[![Version Badge][2]][1]</sup>
  2. [![Build Status][3]][4]
  3. [![dependency status][5]][6]
  4. [![dev dependency status][7]][8]
  5. [![License][license-image]][license-url]
  6. [![Downloads][downloads-image]][downloads-url]
  7. [![npm badge][11]][1]
  8. A querystring parsing and stringifying library with some added security.
  9. Lead Maintainer: [Jordan Harband](https://github.com/ljharb)
  10. The **qs** module was originally created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring).
  11. ## Usage
  12. ```javascript
  13. var qs = require('qs');
  14. var assert = require('assert');
  15. var obj = qs.parse('a=c');
  16. assert.deepEqual(obj, { a: 'c' });
  17. var str = qs.stringify(obj);
  18. assert.equal(str, 'a=c');
  19. ```
  20. ### Parsing Objects
  21. [](#preventEval)
  22. ```javascript
  23. qs.parse(string, [options]);
  24. ```
  25. **qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
  26. For example, the string `'foo[bar]=baz'` converts to:
  27. ```javascript
  28. assert.deepEqual(qs.parse('foo[bar]=baz'), {
  29. foo: {
  30. bar: 'baz'
  31. }
  32. });
  33. ```
  34. 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:
  35. ```javascript
  36. var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
  37. assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
  38. ```
  39. 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.
  40. ```javascript
  41. var protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
  42. assert.deepEqual(protoObject, { a: { hasOwnProperty: 'b' } });
  43. ```
  44. URI encoded strings work too:
  45. ```javascript
  46. assert.deepEqual(qs.parse('a%5Bb%5D=c'), {
  47. a: { b: 'c' }
  48. });
  49. ```
  50. You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`:
  51. ```javascript
  52. assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
  53. foo: {
  54. bar: {
  55. baz: 'foobarbaz'
  56. }
  57. }
  58. });
  59. ```
  60. By default, when nesting objects **qs** will only parse up to 5 children deep. This means if you attempt to parse a string like
  61. `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
  62. ```javascript
  63. var expected = {
  64. a: {
  65. b: {
  66. c: {
  67. d: {
  68. e: {
  69. f: {
  70. '[g][h][i]': 'j'
  71. }
  72. }
  73. }
  74. }
  75. }
  76. }
  77. };
  78. var string = 'a[b][c][d][e][f][g][h][i]=j';
  79. assert.deepEqual(qs.parse(string), expected);
  80. ```
  81. This depth can be overridden by passing a `depth` option to `qs.parse(string, [options])`:
  82. ```javascript
  83. var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
  84. assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
  85. ```
  86. 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.
  87. For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option:
  88. ```javascript
  89. var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
  90. assert.deepEqual(limited, { a: 'b' });
  91. ```
  92. To bypass the leading question mark, use `ignoreQueryPrefix`:
  93. ```javascript
  94. var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });
  95. assert.deepEqual(prefixed, { a: 'b', c: 'd' });
  96. ```
  97. An optional delimiter can also be passed:
  98. ```javascript
  99. var delimited = qs.parse('a=b;c=d', { delimiter: ';' });
  100. assert.deepEqual(delimited, { a: 'b', c: 'd' });
  101. ```
  102. Delimiters can be a regular expression too:
  103. ```javascript
  104. var regexed = qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ });
  105. assert.deepEqual(regexed, { a: 'b', c: 'd', e: 'f' });
  106. ```
  107. Option `allowDots` can be used to enable dot notation:
  108. ```javascript
  109. var withDots = qs.parse('a.b=c', { allowDots: true });
  110. assert.deepEqual(withDots, { a: { b: 'c' } });
  111. ```
  112. ### Parsing Arrays
  113. **qs** can also parse arrays using a similar `[]` notation:
  114. ```javascript
  115. var withArray = qs.parse('a[]=b&a[]=c');
  116. assert.deepEqual(withArray, { a: ['b', 'c'] });
  117. ```
  118. You may specify an index as well:
  119. ```javascript
  120. var withIndexes = qs.parse('a[1]=c&a[0]=b');
  121. assert.deepEqual(withIndexes, { a: ['b', 'c'] });
  122. ```
  123. 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
  124. to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving
  125. their order:
  126. ```javascript
  127. var noSparse = qs.parse('a[1]=b&a[15]=c');
  128. assert.deepEqual(noSparse, { a: ['b', 'c'] });
  129. ```
  130. Note that an empty string is also a value, and will be preserved:
  131. ```javascript
  132. var withEmptyString = qs.parse('a[]=&a[]=b');
  133. assert.deepEqual(withEmptyString, { a: ['', 'b'] });
  134. var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
  135. assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
  136. ```
  137. **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
  138. instead be converted to an object with the index as the key:
  139. ```javascript
  140. var withMaxIndex = qs.parse('a[100]=b');
  141. assert.deepEqual(withMaxIndex, { a: { '100': 'b' } });
  142. ```
  143. This limit can be overridden by passing an `arrayLimit` option:
  144. ```javascript
  145. var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
  146. assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
  147. ```
  148. To disable array parsing entirely, set `parseArrays` to `false`.
  149. ```javascript
  150. var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
  151. assert.deepEqual(noParsingArrays, { a: { '0': 'b' } });
  152. ```
  153. If you mix notations, **qs** will merge the two items into an object:
  154. ```javascript
  155. var mixedNotation = qs.parse('a[0]=b&a[b]=c');
  156. assert.deepEqual(mixedNotation, { a: { '0': 'b', b: 'c' } });
  157. ```
  158. You can also create arrays of objects:
  159. ```javascript
  160. var arraysOfObjects = qs.parse('a[][b]=c');
  161. assert.deepEqual(arraysOfObjects, { a: [{ b: 'c' }] });
  162. ```
  163. ### Stringifying
  164. [](#preventEval)
  165. ```javascript
  166. qs.stringify(object, [options]);
  167. ```
  168. When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
  169. ```javascript
  170. assert.equal(qs.stringify({ a: 'b' }), 'a=b');
  171. assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
  172. ```
  173. This encoding can be disabled by setting the `encode` option to `false`:
  174. ```javascript
  175. var unencoded = qs.stringify({ a: { b: 'c' } }, { encode: false });
  176. assert.equal(unencoded, 'a[b]=c');
  177. ```
  178. Encoding can be disabled for keys by setting the `encodeValuesOnly` option to `true`:
  179. ```javascript
  180. var encodedValues = qs.stringify(
  181. { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
  182. { encodeValuesOnly: true }
  183. );
  184. assert.equal(encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h');
  185. ```
  186. This encoding can also be replaced by a custom encoding method set as `encoder` option:
  187. ```javascript
  188. var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) {
  189. // Passed in values `a`, `b`, `c`
  190. return // Return encoded string
  191. }})
  192. ```
  193. _(Note: the `encoder` option does not apply if `encode` is `false`)_
  194. Analogue to the `encoder` there is a `decoder` option for `parse` to override decoding of properties and values:
  195. ```javascript
  196. var decoded = qs.parse('x=z', { decoder: function (str) {
  197. // Passed in values `x`, `z`
  198. return // Return decoded string
  199. }})
  200. ```
  201. 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.
  202. When arrays are stringified, by default they are given explicit indices:
  203. ```javascript
  204. qs.stringify({ a: ['b', 'c', 'd'] });
  205. // 'a[0]=b&a[1]=c&a[2]=d'
  206. ```
  207. You may override this by setting the `indices` option to `false`:
  208. ```javascript
  209. qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
  210. // 'a=b&a=c&a=d'
  211. ```
  212. You may use the `arrayFormat` option to specify the format of the output array:
  213. ```javascript
  214. qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
  215. // 'a[0]=b&a[1]=c'
  216. qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
  217. // 'a[]=b&a[]=c'
  218. qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
  219. // 'a=b&a=c'
  220. ```
  221. When objects are stringified, by default they use bracket notation:
  222. ```javascript
  223. qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
  224. // 'a[b][c]=d&a[b][e]=f'
  225. ```
  226. You may override this to use dot notation by setting the `allowDots` option to `true`:
  227. ```javascript
  228. qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
  229. // 'a.b.c=d&a.b.e=f'
  230. ```
  231. Empty strings and null values will omit the value, but the equals sign (=) remains in place:
  232. ```javascript
  233. assert.equal(qs.stringify({ a: '' }), 'a=');
  234. ```
  235. Key with no values (such as an empty object or array) will return nothing:
  236. ```javascript
  237. assert.equal(qs.stringify({ a: [] }), '');
  238. assert.equal(qs.stringify({ a: {} }), '');
  239. assert.equal(qs.stringify({ a: [{}] }), '');
  240. assert.equal(qs.stringify({ a: { b: []} }), '');
  241. assert.equal(qs.stringify({ a: { b: {}} }), '');
  242. ```
  243. Properties that are set to `undefined` will be omitted entirely:
  244. ```javascript
  245. assert.equal(qs.stringify({ a: null, b: undefined }), 'a=');
  246. ```
  247. The query string may optionally be prepended with a question mark:
  248. ```javascript
  249. assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
  250. ```
  251. The delimiter may be overridden with stringify as well:
  252. ```javascript
  253. assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
  254. ```
  255. If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
  256. ```javascript
  257. var date = new Date(7);
  258. assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
  259. assert.equal(
  260. qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
  261. 'a=7'
  262. );
  263. ```
  264. You may use the `sort` option to affect the order of parameter keys:
  265. ```javascript
  266. function alphabeticalSort(a, b) {
  267. return a.localeCompare(b);
  268. }
  269. assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
  270. ```
  271. Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
  272. If you pass a function, it will be called for each key to obtain the replacement value. Otherwise, if you
  273. pass an array, it will be used to select properties and array indices for stringification:
  274. ```javascript
  275. function filterFunc(prefix, value) {
  276. if (prefix == 'b') {
  277. // Return an `undefined` value to omit a property.
  278. return;
  279. }
  280. if (prefix == 'e[f]') {
  281. return value.getTime();
  282. }
  283. if (prefix == 'e[g][0]') {
  284. return value * 2;
  285. }
  286. return value;
  287. }
  288. qs.stringify({ a: 'b', c: 'd', e: { f: new Date(123), g: [2] } }, { filter: filterFunc });
  289. // 'a=b&c=d&e[f]=123&e[g][0]=4'
  290. qs.stringify({ a: 'b', c: 'd', e: 'f' }, { filter: ['a', 'e'] });
  291. // 'a=b&e=f'
  292. qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] });
  293. // 'a[0]=b&a[2]=d'
  294. ```
  295. ### Handling of `null` values
  296. By default, `null` values are treated like empty strings:
  297. ```javascript
  298. var withNull = qs.stringify({ a: null, b: '' });
  299. assert.equal(withNull, 'a=&b=');
  300. ```
  301. Parsing does not distinguish between parameters with and without equal signs. Both are converted to empty strings.
  302. ```javascript
  303. var equalsInsensitive = qs.parse('a&b=');
  304. assert.deepEqual(equalsInsensitive, { a: '', b: '' });
  305. ```
  306. To distinguish between `null` values and empty strings use the `strictNullHandling` flag. In the result string the `null`
  307. values have no `=` sign:
  308. ```javascript
  309. var strictNull = qs.stringify({ a: null, b: '' }, { strictNullHandling: true });
  310. assert.equal(strictNull, 'a&b=');
  311. ```
  312. To parse values without `=` back to `null` use the `strictNullHandling` flag:
  313. ```javascript
  314. var parsedStrictNull = qs.parse('a&b=', { strictNullHandling: true });
  315. assert.deepEqual(parsedStrictNull, { a: null, b: '' });
  316. ```
  317. To completely skip rendering keys with `null` values, use the `skipNulls` flag:
  318. ```javascript
  319. var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true });
  320. assert.equal(nullsSkipped, 'a=b');
  321. ```
  322. ### Dealing with special character sets
  323. By default the encoding and decoding of characters is done in `utf-8`. If you
  324. wish to encode querystrings to a different character set (i.e.
  325. [Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the
  326. [`qs-iconv`](https://github.com/martinheidegger/qs-iconv) library:
  327. ```javascript
  328. var encoder = require('qs-iconv/encoder')('shift_jis');
  329. var shiftJISEncoded = qs.stringify({ a: 'こんにちは!' }, { encoder: encoder });
  330. assert.equal(shiftJISEncoded, 'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I');
  331. ```
  332. This also works for decoding of query strings:
  333. ```javascript
  334. var decoder = require('qs-iconv/decoder')('shift_jis');
  335. var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
  336. assert.deepEqual(obj, { a: 'こんにちは!' });
  337. ```
  338. ### RFC 3986 and RFC 1738 space encoding
  339. RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
  340. In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
  341. ```
  342. assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
  343. assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
  344. assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
  345. ```
  346. [1]: https://npmjs.org/package/qs
  347. [2]: http://versionbadg.es/ljharb/qs.svg
  348. [3]: https://api.travis-ci.org/ljharb/qs.svg
  349. [4]: https://travis-ci.org/ljharb/qs
  350. [5]: https://david-dm.org/ljharb/qs.svg
  351. [6]: https://david-dm.org/ljharb/qs
  352. [7]: https://david-dm.org/ljharb/qs/dev-status.svg
  353. [8]: https://david-dm.org/ljharb/qs?type=dev
  354. [9]: https://ci.testling.com/ljharb/qs.png
  355. [10]: https://ci.testling.com/ljharb/qs
  356. [11]: https://nodei.co/npm/qs.png?downloads=true&stars=true
  357. [license-image]: http://img.shields.io/npm/l/qs.svg
  358. [license-url]: LICENSE
  359. [downloads-image]: http://img.shields.io/npm/dm/qs.svg
  360. [downloads-url]: http://npm-stat.com/charts.html?package=qs