source: frontend/node_modules/qs/README.md

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 26.3 KB
Line 
1<p align="center">
2 <img alt="qs" src="./logos/banner_default.png" width="800" />
3</p>
4
5# qs <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
6
7[![github actions][actions-image]][actions-url]
8[![coverage][codecov-image]][codecov-url]
9[![License][license-image]][license-url]
10[![Downloads][downloads-image]][downloads-url]
11[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/9058/badge)](https://bestpractices.coreinfrastructure.org/projects/9058)
12
13[![npm badge][npm-badge-png]][package-url]
14
15A querystring parsing and stringifying library with some added security.
16
17Lead Maintainer: [Jordan Harband](https://github.com/ljharb)
18
19The **qs** module was originally created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring).
20
21## Usage
22
23```javascript
24var qs = require('qs');
25var assert = require('assert');
26
27var obj = qs.parse('a=c');
28assert.deepEqual(obj, { a: 'c' });
29
30var str = qs.stringify(obj);
31assert.equal(str, 'a=c');
32```
33
34### Parsing Objects
35
36[](#preventEval)
37```javascript
38qs.parse(string, [options]);
39```
40
41**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
42For example, the string `'foo[bar]=baz'` converts to:
43
44```javascript
45assert.deepEqual(qs.parse('foo[bar]=baz'), {
46 foo: {
47 bar: 'baz'
48 }
49});
50```
51
52When using the `plainObjects` option the parsed value is returned as a null object, created via `{ __proto__: 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:
53
54```javascript
55var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
56assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
57```
58
59By 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.
60*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.
61Always be careful with this option.
62
63```javascript
64var protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
65assert.deepEqual(protoObject, { a: { hasOwnProperty: 'b' } });
66```
67
68URI encoded strings work too:
69
70```javascript
71assert.deepEqual(qs.parse('a%5Bb%5D=c'), {
72 a: { b: 'c' }
73});
74```
75
76You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`:
77
78```javascript
79assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
80 foo: {
81 bar: {
82 baz: 'foobarbaz'
83 }
84 }
85});
86```
87
88By default, when nesting objects **qs** will only parse up to 5 children deep.
89This means if you attempt to parse a string like `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
90
91```javascript
92var expected = {
93 a: {
94 b: {
95 c: {
96 d: {
97 e: {
98 f: {
99 '[g][h][i]': 'j'
100 }
101 }
102 }
103 }
104 }
105 }
106};
107var string = 'a[b][c][d][e][f][g][h][i]=j';
108assert.deepEqual(qs.parse(string), expected);
109```
110
111This depth can be overridden by passing a `depth` option to `qs.parse(string, [options])`:
112
113```javascript
114var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
115assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
116```
117
118You can configure **qs** to throw an error when parsing nested input beyond this depth using the `strictDepth` option (defaulted to false):
119
120```javascript
121try {
122 qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true });
123} catch (err) {
124 assert(err instanceof RangeError);
125 assert.strictEqual(err.message, 'Input depth exceeded depth option of 1 and strictDepth is true');
126}
127```
128
129The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. The strictDepth option adds a layer of protection by throwing an error when the limit is exceeded, allowing you to catch and handle such cases.
130
131For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option:
132
133```javascript
134var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
135assert.deepEqual(limited, { a: 'b' });
136```
137
138If you want an error to be thrown whenever the a limit is exceeded (eg, `parameterLimit`, `arrayLimit`), set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
139```javascript
140try {
141 qs.parse('a=1&b=2&c=3&d=4', { parameterLimit: 3, throwOnLimitExceeded: true });
142} catch (err) {
143 assert(err instanceof Error);
144 assert.strictEqual(err.message, 'Parameter limit exceeded. Only 3 parameters allowed.');
145}
146```
147
148When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error.
149
150To bypass the leading question mark, use `ignoreQueryPrefix`:
151
152```javascript
153var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });
154assert.deepEqual(prefixed, { a: 'b', c: 'd' });
155```
156
157An optional delimiter can also be passed:
158
159```javascript
160var delimited = qs.parse('a=b;c=d', { delimiter: ';' });
161assert.deepEqual(delimited, { a: 'b', c: 'd' });
162```
163
164Delimiters can be a regular expression too:
165
166```javascript
167var regexed = qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ });
168assert.deepEqual(regexed, { a: 'b', c: 'd', e: 'f' });
169```
170
171Option `allowDots` can be used to enable dot notation:
172
173```javascript
174var withDots = qs.parse('a.b=c', { allowDots: true });
175assert.deepEqual(withDots, { a: { b: 'c' } });
176```
177
178Option `decodeDotInKeys` can be used to decode dots in keys
179Note: it implies `allowDots`, so `parse` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
180
181```javascript
182var withDots = qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { decodeDotInKeys: true });
183assert.deepEqual(withDots, { 'name.obj': { first: 'John', last: 'Doe' }});
184```
185
186Option `allowEmptyArrays` can be used to allow empty array values in an object
187```javascript
188var withEmptyArrays = qs.parse('foo[]&bar=baz', { allowEmptyArrays: true });
189assert.deepEqual(withEmptyArrays, { foo: [], bar: 'baz' });
190```
191
192Option `duplicates` can be used to change the behavior when duplicate keys are encountered
193```javascript
194assert.deepEqual(qs.parse('foo=bar&foo=baz'), { foo: ['bar', 'baz'] });
195assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'combine' }), { foo: ['bar', 'baz'] });
196assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'first' }), { foo: 'bar' });
197assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'last' }), { foo: 'baz' });
198```
199
200Note that keys with bracket notation (`[]`) always combine into arrays, regardless of the `duplicates` setting:
201```javascript
202assert.deepEqual(qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'last' }), { a: '2', b: ['1', '2'] });
203```
204
205If you have to deal with legacy browsers or services, there's also support for decoding percent-encoded octets as iso-8859-1:
206
207```javascript
208var oldCharset = qs.parse('a=%A7', { charset: 'iso-8859-1' });
209assert.deepEqual(oldCharset, { a: '§' });
210```
211
212Some services add an initial `utf8=✓` value to forms so that old Internet Explorer versions are more likely to submit the form as utf-8.
213Additionally, the server can check the value against wrong encodings of the checkmark character and detect that a query string or `application/x-www-form-urlencoded` body was *not* sent as utf-8, eg. if the form had an `accept-charset` parameter or the containing page had a different character set.
214
215**qs** supports this mechanism via the `charsetSentinel` option.
216If specified, the `utf8` parameter will be omitted from the returned object.
217It will be used to switch to `iso-8859-1`/`utf-8` mode depending on how the checkmark is encoded.
218
219**Important**: When you specify both the `charset` option and the `charsetSentinel` option, the `charset` will be overridden when the request contains a `utf8` parameter from which the actual charset can be deduced.
220In that sense the `charset` will behave as the default charset rather than the authoritative charset.
221
222```javascript
223var detectedAsUtf8 = qs.parse('utf8=%E2%9C%93&a=%C3%B8', {
224 charset: 'iso-8859-1',
225 charsetSentinel: true
226});
227assert.deepEqual(detectedAsUtf8, { a: 'ø' });
228
229// Browsers encode the checkmark as &#10003; when submitting as iso-8859-1:
230var detectedAsIso8859_1 = qs.parse('utf8=%26%2310003%3B&a=%F8', {
231 charset: 'utf-8',
232 charsetSentinel: true
233});
234assert.deepEqual(detectedAsIso8859_1, { a: 'ø' });
235```
236
237If you want to decode the `&#...;` syntax to the actual character, you can specify the `interpretNumericEntities` option as well:
238
239```javascript
240var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', {
241 charset: 'iso-8859-1',
242 interpretNumericEntities: true
243});
244assert.deepEqual(detectedAsIso8859_1, { a: '☺' });
245```
246
247It also works when the charset has been detected in `charsetSentinel` mode.
248
249### Parsing Arrays
250
251**qs** can also parse arrays using a similar `[]` notation:
252
253```javascript
254var withArray = qs.parse('a[]=b&a[]=c');
255assert.deepEqual(withArray, { a: ['b', 'c'] });
256```
257
258You may specify an index as well:
259
260```javascript
261var withIndexes = qs.parse('a[1]=c&a[0]=b');
262assert.deepEqual(withIndexes, { a: ['b', 'c'] });
263```
264
265Note 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 to create an array.
266When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving their order:
267
268```javascript
269var noSparse = qs.parse('a[1]=b&a[15]=c');
270assert.deepEqual(noSparse, { a: ['b', 'c'] });
271```
272
273You may also use `allowSparse` option to parse sparse arrays:
274
275```javascript
276var sparseArray = qs.parse('a[1]=2&a[3]=5', { allowSparse: true });
277assert.deepEqual(sparseArray, { a: [, '2', , '5'] });
278```
279
280Note that an empty string is also a value, and will be preserved:
281
282```javascript
283var withEmptyString = qs.parse('a[]=&a[]=b');
284assert.deepEqual(withEmptyString, { a: ['', 'b'] });
285
286var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
287assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
288```
289
290**qs** will also limit arrays to a maximum of `20` elements.
291Any array members with an index of `20` or greater will instead be converted to an object with the index as the key.
292This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
293
294```javascript
295var withMaxIndex = qs.parse('a[100]=b');
296assert.deepEqual(withMaxIndex, { a: { '100': 'b' } });
297```
298
299This limit can be overridden by passing an `arrayLimit` option:
300
301```javascript
302var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
303assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
304```
305
306If you want to throw an error whenever the array limit is exceeded, set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
307```javascript
308try {
309 qs.parse('a[1]=b', { arrayLimit: 0, throwOnLimitExceeded: true });
310} catch (err) {
311 assert(err instanceof Error);
312 assert.strictEqual(err.message, 'Array limit exceeded. Only 0 elements allowed in an array.');
313}
314```
315
316When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `arrayLimit` and if the limit is exceeded, the array will instead be converted to an object with the index as the key
317
318To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
319Note that duplicate keys (e.g. `a=b&a=c`) may still produce arrays when `duplicates` is `'combine'` (the default).
320
321```javascript
322var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
323assert.deepEqual(noParsingArrays, { a: { '0': 'b' } });
324```
325
326If you mix notations, **qs** will merge the two items into an object:
327
328```javascript
329var mixedNotation = qs.parse('a[0]=b&a[b]=c');
330assert.deepEqual(mixedNotation, { a: { '0': 'b', b: 'c' } });
331```
332
333When a key appears as both a plain value and an object, **qs** will by default wrap the conflicting values in an array (`strictMerge` defaults to `true`):
334
335```javascript
336assert.deepEqual(qs.parse('a[b]=c&a=d'), { a: [{ b: 'c' }, 'd'] });
337assert.deepEqual(qs.parse('a=d&a[b]=c'), { a: ['d', { b: 'c' }] });
338```
339
340To restore the legacy behavior (where the primitive is used as a key with value `true`), set `strictMerge` to `false`:
341
342```javascript
343assert.deepEqual(qs.parse('a[b]=c&a=d', { strictMerge: false }), { a: { b: 'c', d: true } });
344```
345
346You can also create arrays of objects:
347
348```javascript
349var arraysOfObjects = qs.parse('a[][b]=c');
350assert.deepEqual(arraysOfObjects, { a: [{ b: 'c' }] });
351```
352
353Some people use comma to join array, **qs** can parse it:
354```javascript
355var arraysOfObjects = qs.parse('a=b,c', { comma: true })
356assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] })
357```
358(_this cannot convert nested objects, such as `a={b:1},{c:d}`_)
359
360### Parsing primitive/scalar values (numbers, booleans, null, etc)
361
362By default, all values are parsed as strings.
363This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
364
365```javascript
366var primitiveValues = qs.parse('a=15&b=true&c=null');
367assert.deepEqual(primitiveValues, { a: '15', b: 'true', c: 'null' });
368```
369
370If you wish to auto-convert values which look like numbers, booleans, and other values into their primitive counterparts, you can use the [query-types Express JS middleware](https://github.com/xpepermint/query-types) which will auto-convert all request query parameters.
371
372### Stringifying
373
374[](#preventEval)
375```javascript
376qs.stringify(object, [options]);
377```
378
379When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
380
381```javascript
382assert.equal(qs.stringify({ a: 'b' }), 'a=b');
383assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
384```
385
386This encoding can be disabled by setting the `encode` option to `false`:
387
388```javascript
389var unencoded = qs.stringify({ a: { b: 'c' } }, { encode: false });
390assert.equal(unencoded, 'a[b]=c');
391```
392
393Encoding can be disabled for keys by setting the `encodeValuesOnly` option to `true`:
394```javascript
395var encodedValues = qs.stringify(
396 { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
397 { encodeValuesOnly: true }
398);
399assert.equal(encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h');
400```
401
402This encoding can also be replaced by a custom encoding method set as `encoder` option:
403
404```javascript
405var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) {
406 // Passed in values `a`, `b`, `c`
407 return // Return encoded string
408}})
409```
410
411_(Note: the `encoder` option does not apply if `encode` is `false`)_
412
413Analogue to the `encoder` there is a `decoder` option for `parse` to override decoding of properties and values:
414
415```javascript
416var decoded = qs.parse('x=z', { decoder: function (str) {
417 // Passed in values `x`, `z`
418 return // Return decoded string
419}})
420```
421
422You can encode keys and values using different logic by using the type argument provided to the encoder:
423
424```javascript
425var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) {
426 if (type === 'key') {
427 return // Encoded key
428 } else if (type === 'value') {
429 return // Encoded value
430 }
431}})
432```
433
434The type argument is also provided to the decoder:
435
436```javascript
437var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, type) {
438 if (type === 'key') {
439 return // Decoded key
440 } else if (type === 'value') {
441 return // Decoded value
442 }
443}})
444```
445
446Examples beyond this point will be shown as though the output is not URI encoded for clarity.
447Please note that the return values in these cases *will* be URI encoded during real usage.
448
449When arrays are stringified, they follow the `arrayFormat` option, which defaults to `indices`:
450
451```javascript
452qs.stringify({ a: ['b', 'c', 'd'] });
453// 'a[0]=b&a[1]=c&a[2]=d'
454```
455
456You may override this by setting the `indices` option to `false`, or to be more explicit, the `arrayFormat` option to `repeat`:
457
458```javascript
459qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
460// 'a=b&a=c&a=d'
461```
462
463You may use the `arrayFormat` option to specify the format of the output array:
464
465```javascript
466qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
467// 'a[0]=b&a[1]=c'
468qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
469// 'a[]=b&a[]=c'
470qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
471// 'a=b&a=c'
472qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
473// 'a=b,c'
474```
475
476Note: when using `arrayFormat` set to `'comma'`, you can also pass the `commaRoundTrip` option set to `true` or `false`, to append `[]` on single-item arrays, so that they can round trip through a parse.
477
478When objects are stringified, by default they use bracket notation:
479
480```javascript
481qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
482// 'a[b][c]=d&a[b][e]=f'
483```
484
485You may override this to use dot notation by setting the `allowDots` option to `true`:
486
487```javascript
488qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
489// 'a.b.c=d&a.b.e=f'
490```
491
492You may encode the dot notation in the keys of object with option `encodeDotInKeys` by setting it to `true`:
493Note: it implies `allowDots`, so `stringify` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
494Caveat: when `encodeValuesOnly` is `true` as well as `encodeDotInKeys`, only dots in keys and nothing else will be encoded.
495```javascript
496qs.stringify({ "name.obj": { "first": "John", "last": "Doe" } }, { allowDots: true, encodeDotInKeys: true })
497// 'name%252Eobj.first=John&name%252Eobj.last=Doe'
498```
499
500You may allow empty array values by setting the `allowEmptyArrays` option to `true`:
501```javascript
502qs.stringify({ foo: [], bar: 'baz' }, { allowEmptyArrays: true });
503// 'foo[]&bar=baz'
504```
505
506Empty strings and null values will omit the value, but the equals sign (=) remains in place:
507
508```javascript
509assert.equal(qs.stringify({ a: '' }), 'a=');
510```
511
512Key with no values (such as an empty object or array) will return nothing:
513
514```javascript
515assert.equal(qs.stringify({ a: [] }), '');
516assert.equal(qs.stringify({ a: {} }), '');
517assert.equal(qs.stringify({ a: [{}] }), '');
518assert.equal(qs.stringify({ a: { b: []} }), '');
519assert.equal(qs.stringify({ a: { b: {}} }), '');
520```
521
522Properties that are set to `undefined` will be omitted entirely:
523
524```javascript
525assert.equal(qs.stringify({ a: null, b: undefined }), 'a=');
526```
527
528The query string may optionally be prepended with a question mark:
529
530```javascript
531assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
532```
533
534Note that when the output is an empty string, the prefix will not be added:
535
536```javascript
537assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
538```
539
540The delimiter may be overridden with stringify as well:
541
542```javascript
543assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
544```
545
546If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
547
548```javascript
549var date = new Date(7);
550assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
551assert.equal(
552 qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
553 'a=7'
554);
555```
556
557You may use the `sort` option to affect the order of parameter keys:
558
559```javascript
560function alphabeticalSort(a, b) {
561 return a.localeCompare(b);
562}
563assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
564```
565
566Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
567If you pass a function, it will be called for each key to obtain the replacement value.
568Otherwise, if you pass an array, it will be used to select properties and array indices for stringification:
569
570```javascript
571function filterFunc(prefix, value) {
572 if (prefix == 'b') {
573 // Return an `undefined` value to omit a property.
574 return;
575 }
576 if (prefix == 'e[f]') {
577 return value.getTime();
578 }
579 if (prefix == 'e[g][0]') {
580 return value * 2;
581 }
582 return value;
583}
584qs.stringify({ a: 'b', c: 'd', e: { f: new Date(123), g: [2] } }, { filter: filterFunc });
585// 'a=b&c=d&e[f]=123&e[g][0]=4'
586qs.stringify({ a: 'b', c: 'd', e: 'f' }, { filter: ['a', 'e'] });
587// 'a=b&e=f'
588qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] });
589// 'a[0]=b&a[2]=d'
590```
591
592You could also use `filter` to inject custom serialization for user defined types.
593Consider you're working with some api that expects query strings of the format for ranges:
594
595```
596https://domain.com/endpoint?range=30...70
597```
598
599For which you model as:
600
601```javascript
602class Range {
603 constructor(from, to) {
604 this.from = from;
605 this.to = to;
606 }
607}
608```
609
610You could _inject_ a custom serializer to handle values of this type:
611
612```javascript
613qs.stringify(
614 {
615 range: new Range(30, 70),
616 },
617 {
618 filter: (prefix, value) => {
619 if (value instanceof Range) {
620 return `${value.from}...${value.to}`;
621 }
622 // serialize the usual way
623 return value;
624 },
625 }
626);
627// range=30...70
628```
629
630### Handling of `null` values
631
632By default, `null` values are treated like empty strings:
633
634```javascript
635var withNull = qs.stringify({ a: null, b: '' });
636assert.equal(withNull, 'a=&b=');
637```
638
639Parsing does not distinguish between parameters with and without equal signs.
640Both are converted to empty strings.
641
642```javascript
643var equalsInsensitive = qs.parse('a&b=');
644assert.deepEqual(equalsInsensitive, { a: '', b: '' });
645```
646
647To distinguish between `null` values and empty strings use the `strictNullHandling` flag. In the result string the `null`
648values have no `=` sign:
649
650```javascript
651var strictNull = qs.stringify({ a: null, b: '' }, { strictNullHandling: true });
652assert.equal(strictNull, 'a&b=');
653```
654
655To parse values without `=` back to `null` use the `strictNullHandling` flag:
656
657```javascript
658var parsedStrictNull = qs.parse('a&b=', { strictNullHandling: true });
659assert.deepEqual(parsedStrictNull, { a: null, b: '' });
660```
661
662To completely skip rendering keys with `null` values, use the `skipNulls` flag:
663
664```javascript
665var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true });
666assert.equal(nullsSkipped, 'a=b');
667```
668
669If you're communicating with legacy systems, you can switch to `iso-8859-1` using the `charset` option:
670
671```javascript
672var iso = qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' });
673assert.equal(iso, '%E6=%E6');
674```
675
676Characters that don't exist in `iso-8859-1` will be converted to numeric entities, similar to what browsers do:
677
678```javascript
679var numeric = qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' });
680assert.equal(numeric, 'a=%26%239786%3B');
681```
682
683You can use the `charsetSentinel` option to announce the character by including an `utf8=✓` parameter with the proper encoding if the checkmark, similar to what Ruby on Rails and others do when submitting forms.
684
685```javascript
686var sentinel = qs.stringify({ a: '☺' }, { charsetSentinel: true });
687assert.equal(sentinel, 'utf8=%E2%9C%93&a=%E2%98%BA');
688
689var isoSentinel = qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' });
690assert.equal(isoSentinel, 'utf8=%26%2310003%3B&a=%E6');
691```
692
693### Dealing with special character sets
694
695By default the encoding and decoding of characters is done in `utf-8`, and `iso-8859-1` support is also built in via the `charset` parameter.
696
697If you wish to encode querystrings to a different character set (i.e.
698[Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the
699[`qs-iconv`](https://github.com/martinheidegger/qs-iconv) library:
700
701```javascript
702var encoder = require('qs-iconv/encoder')('shift_jis');
703var shiftJISEncoded = qs.stringify({ a: 'こんにちは!' }, { encoder: encoder });
704assert.equal(shiftJISEncoded, 'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I');
705```
706
707This also works for decoding of query strings:
708
709```javascript
710var decoder = require('qs-iconv/decoder')('shift_jis');
711var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
712assert.deepEqual(obj, { a: 'こんにちは!' });
713```
714
715### RFC 3986 and RFC 1738 space encoding
716
717RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
718In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
719
720```
721assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
722assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
723assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
724```
725
726## Security
727
728Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.
729
730## qs for enterprise
731
732Available as part of the Tidelift Subscription
733
734The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications.
735Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
736[Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
737
738[package-url]: https://npmjs.org/package/qs
739[npm-version-svg]: https://versionbadg.es/ljharb/qs.svg
740[deps-svg]: https://david-dm.org/ljharb/qs.svg
741[deps-url]: https://david-dm.org/ljharb/qs
742[dev-deps-svg]: https://david-dm.org/ljharb/qs/dev-status.svg
743[dev-deps-url]: https://david-dm.org/ljharb/qs#info=devDependencies
744[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true
745[license-image]: https://img.shields.io/npm/l/qs.svg
746[license-url]: LICENSE
747[downloads-image]: https://img.shields.io/npm/dm/qs.svg
748[downloads-url]: https://npm-stat.com/charts.html?package=qs
749[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
750[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
751[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
752[actions-url]: https://github.com/ljharb/qs/actions
753
754## Acknowledgements
755
756qs logo by [NUMI](https://github.com/numi-hq/open-design):
757
758[<img src="https://raw.githubusercontent.com/numi-hq/open-design/main/assets/numi-lockup.png" alt="NUMI Logo" style="width: 200px;"/>](https://numi.tech/?ref=qs)
Note: See TracBrowser for help on using the repository browser.