This article basically uses Google Translate to add your own understanding, just to deepen your memory.
npm
Introduction
qs is a library that adds some security to query string parsing and serializing strings.
Main Maintenancer: Jordan Harband
Original creator and maintainer: TJ Holowaychuk
usage
var qs = require('qs'); var assert = require('assert'); var obj = ('a=c'); (obj, { a: 'c' }); var str = (obj); (str, 'a=c');
Resolve objects
(string, [options]);
qs allows the creation of nested objects in the query string using the [] method. For example, the string 'foo[bar]=baz' can be converted to:
(('foo[bar]=baz'), { foo: { bar: 'baz' } });
When using the plainObjects option the parsed value is returned as a null object, created via (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:
var nullObject = ('a[hasOwnProperty]=b', { plainObjects: true }); (nullObject, { a: { hasOwnProperty: 'b' } });
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.
var protoObject = ('a[hasOwnProperty]=b', { allowPrototypes: true }); (protoObject, { a: { hasOwnProperty: 'b' } });
You can also parse the URI encoding:
(('a%5Bb%5D=c'), { a: { b: 'c' } });
You can also nest objects like this: 'foo[bar][baz]=foobarbaz':
(('foo[bar][baz]=foobarbaz'), { foo: { bar: { baz: 'foobarbaz' } } });
When using nested objects, the maximum depth to which qs parses by default is the fifth layer (note: from the first square bracket to the fifth square bracket). For example, trying to parse a string such as 'a[b][c][d][e][f][g][h][i]=j' will get the following result:
var expected = { a: { b: { c: { d: { e: { f: { '[g][h][i]': 'j' } } } } } } }; var string = 'a[b][c][d][e][f][g][h][i]=j'; ((string), expected);
You can pass a depth parameter to override the default value:
var deep = ('a[b][c][d][e][f][g][h][i]=j', { depth: 1 }); (deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
When qs is used to parse user input, the limitation of parsing depth helps to alleviate user abuse. It is best to set depth to a reasonable number as small as possible.
For similar reasons, qs parses up to 1000 parameters by default. By passing the parameterLimit parameter, you can modify the default value:
var limited = ('a=b&c=d', { parameterLimit: 1 }); (limited, { a: 'b' });
Ignore the beginning of the query string? You can use ignoreQueryPrefix:
var prefixed = ('?a=b&c=d', { ignoreQueryPrefix: true }); (prefixed, { a: 'b', c: 'd' });
Delimiters can also be parsed based on custom delimiters:
var delimited = ('a=b;c=d', { delimiter: ';' }); (delimited, { a: 'b', c: 'd' });
The delimiter can be a regular expression:
var regexed = ('a=b;c=d,e=f', { delimiter: /[;,]/ }); (regexed, { a: 'b', c: 'd', e: 'f' });
The allowDots option enables dot notation:
var withDots = ('=c', { allowDots: true }); (withDots, { a: { b: 'c' } });
Analyze the array
qs can also be used to parse arrays with []:
var withArray = ('a[]=b&a[]=c'); (withArray, { a: ['b', 'c'] });
You can specify an array index:
var withIndexes = ('a[1]=c&a[0]=b'); (withIndexes, { a: ['b', 'c'] });
Note that if you want to parse a string into an array instead of an object, the value between [] must be a number. When creating an array with a specific index, qs compresses the sparse array to existing values that retain only their order:
var noSparse = ('a[1]=b&a[15]=c'); (noSparse, { a: ['b', 'c'] });
An empty string is also a value and will be preserved:
var withEmptyString = ('a[]=&a[]=b'); (withEmptyString, { a: ['', 'b'] }); var withIndexedEmptyString = ('a[0]=b&a[1]=&a[2]=c'); (withIndexedEmptyString, { a: ['b', '', 'c'] });
qs will also limit the array's maximum index to 20, and any array member with an index greater than 20 will be converted into an object with the index as the key:
var withMaxIndex = ('a[100]=b'); (withMaxIndex, { a: { '100': 'b' } });
The arrayLimit option can modify the default limit:
var withArrayLimit = ('a[1]=b', { arrayLimit: 0 }); (withArrayLimit, { a: { '1': 'b' } });
The string does not resolve into an array, you can set parseArrays to false
var noParsingArrays = ('a[]=b', { parseArrays: false }); (noParsingArrays, { a: { '0': 'b' } });
If you use two formats in a mix, qs parses the string into an object:
var mixedNotation = ('a[0]=b&a[b]=c'); (mixedNotation, { a: { '0': 'b', b: 'c' } });
You can also create an array of elements as objects:
var arraysOfObjects = ('a[][b]=c'); (arraysOfObjects, { a: [{ b: 'c' }] });
Serialize strings
(object, [options]);
By default, the object is serialized and URI-encoded and output:
(({ a: 'b' }), 'a=b'); (({ a: { b: 'c' } }), 'a%5Bb%5D=c');
Disable URI encoding by setting encode to false:
var unencoded = ({ a: { b: 'c' } }, { encode: false }); (unencoded, 'a[b]=c');
By setting encodeValuesOnly to true, URI encoding of keys can be disabled:
var encodedValues = ( { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] }, { encodeValuesOnly: true } ); (encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h');
You can customize the encoding method by setting the encoder option (note: it is not applicable when encode is set to false):
var encoded = ({ a: { b: 'c' } }, { encoder: function (str) { // Passed in values `a`, `b`, `c` return // Return encoded string }})
Similar to encoder decoder can be used to decode:
var decoded = ('x=z', { decoder: function (str) { // Passed in values `x`, `z` return // Return decoded string }})
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.
When an array is serialized, the index is displayed by default:
({ a: ['b', 'c', 'd'] }); // 'a[0]=b&a[1]=c&a[2]=d'
You can set indices to false to not display the index:
({ a: ['b', 'c', 'd'] }, { indices: false }); // 'a=b&a=c&a=d'
The array output format can be specified by setting the arrayFormat option:
({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) // 'a[0]=b&a[1]=c' ({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) // 'a[]=b&a[]=c' ({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) // 'a=b&a=c'
When object serialization, the [] notation is used by default:
({ a: { b: { c: 'd', e: 'f' } } }); // 'a[b][c]=d&a[b][e]=f'
Modify to point notation by setting allowDots to true:
({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true }); // '=d&=f'
Empty strings and null values will be omitted, but = will be preserved:
(({ a: '' }), 'a=');
A key without a value will return nothing (e.g. an empty object or an array):
(({ a: [] }), ''); (({ a: {} }), ''); (({ a: [{}] }), ''); (({ a: { b: []} }), ''); (({ a: { b: {}} }), '');
Properties with value undefined will be completely ignored:
(({ a: null, b: undefined }), 'a=');
If addQueryPrefix is set to true, you can add ? before the query string:
(({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
The delimiter can also be set:
(({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
If you are just serializing the date object, you can use the serializeDate option:
var date = new Date(7); (({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A')); ( ({ a: date }, { serializeDate: function (d) { return (); } }), 'a=7' );
You can use the sort option to modify the order of keys:
function alphabeticalSort(a, b) { return (b); } (({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
Finally, you can use the filter option to filter the serialized output keys. If you pass a function to filter, each key calls the function once and replaces the original value with the returned value. If you pass an array to filter, it will be used to select the key of the object and the index of the array:
function filterFunc(prefix, value) { if (prefix == 'b') { // Return an `undefined` value to omit a property. return; } if (prefix == 'e[f]') { return (); } if (prefix == 'e[g][0]') { return value * 2; } return value; } ({ a: 'b', c: 'd', e: { f: new Date(123), g: [2] } }, { filter: filterFunc }); // 'a=b&c=d&e[f]=123&e[g][0]=4' ({ a: 'b', c: 'd', e: 'f' }, { filter: ['a', 'e'] }); // 'a=b&e=f' ({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] }); // 'a[0]=b&a[2]=d'
Process null values
By default, the null value is treated as an empty object:
var withNull = ({ a: null, b: '' }); (withNull, 'a=&b=');
When parsing a string, it will not distinguish whether the parameter has an equal sign. If there is no value, it will be parsed into an empty string:
var equalsInsensitive = ('a&b='); (equalsInsensitive, { a: '', b: '' });
To distinguish between empty strings and null values, you can use the strictNullHandling option. The serialized null value does not have =
var strictNull = ({ a: null, b: '' }, { strictNullHandling: true }); (strictNull, 'a&b=');
To parse a value without = return null, use the strictNullHandling option:
var parsedStrictNull = ('a&b=', { strictNullHandling: true }); (parsedStrictNull, { a: null, b: '' });
To completely skip keys with a value of null without parsing, you can use the skipNulls option:
var nullsSkipped = ({ a: 'b', c: null}, { skipNulls: true }); (nullsSkipped, 'a=b');
Handling special character sets:
By default, the encoding and decoding of characters is done in utf-8. If you want to encode the query string into a different character set (JIS), you can use the qs-iconv library:
var encoder = require('qs-iconv/encoder')('shift_jis'); var shiftJISEncoded = ({ a: 'こんにちは!' }, { encoder: encoder }); (shiftJISEncoded, 'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I');
This also works for decoding query strings:
var decoder = require('qs-iconv/decoder')('shift_jis'); var obj = ('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder }); (obj, { a: 'こんにちは!' });
RFC 3986 and RFC 1738 space encoding
RFC3986 used as default option and encodes ' ' to %20 which is backward compatible. In the same time, output can be stringified as per RFC1738 with ' ' equal to ‘+'.
(({ a: 'b c' }), 'a=b%20c'); (({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c'); (({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.