安裝
npm install qs
使用
let qs = require('qs')
// 或者 import qs from 'qs'
方法
- 對象序列化爲URL查詢參數
let obj = {a: 1, b: 2, c: 3};
let str = qs.stringify(obj); // a=1&b=2&c=3
- URL查詢參數解析爲對象
let str = 'a=1&b=2&c=3';
let obj = qs.parse(obj); // {a: 1, b: 2, c: 3}
常用參數
qs.parse(string, options)
參數名 | 默認值 | 說明 |
---|---|---|
plainObjects | false | 是否通過Object.create(null)方式創建新對象,如果是,則返回的對象不具有Object的原型方法,且可以指定原型對象的屬性值 |
allowPrototypes | false | 是否允許指定原型屬性的值 |
depth | 5 | qs把字符串解析爲對象時,可以解析URI編碼過的字符,也可以解析嵌套子對象,子對象支持用[]來表示,默認最多支持嵌套5層,該屬性可以修改支持的嵌套層數 |
parameterLimit | 1000 | 可以解析的參數個數,默認1000個鍵值對,超過的會忽略 |
ignoreQueryPrefix | false | 字符串開頭的?是否忽略,默認會解析到第一個參數的key裏 |
delimiter | & | 連接字符串的分割符,可以是一個字符串,也可以是正則,滿足的都支持解析 例如: /[;,]/ |
allowDots | false | 嵌套子對象的表示方式,是否支持.表示,默認false時,是[]表示 |
chartset | utf-8 | 編碼格式 |
decoder | function(str){} | 自定義解碼方法 |
comma | false | 是否支持逗號連接的值轉爲數組, a={b:1},{c:d}的除外 |
arrayLimit | 20 | 數組最大索引值, 超過的話會按照對象來解析 |
parseArrays | true | 是否按照數組規則解析爲數組,如果爲false,則全部按照對象格式解析 |
qs.stringify(object, [options])
參數名稱 | 默認值 | 說明 |
---|---|---|
encode | true | 默認會對序列化後的字符串進行utf-8編碼 |
encodeValuesOnly | false | 是否只對值編碼 |
encoder | function(str){} | 自定義編碼方法, encode爲false時無效 |
indices | true | 數組的序列化,是否要顯式序列化索引, false: ‘a=b&a=c&a=d’, true: a[0]=b&a[1]=c&a[2]=d |
arrayFormat | indices/brackets/repeat/comma | indices:顯示序列化數組索引;brackets: 只用中括號表示;repeat: 重複可以來表示數組;comma: 數組值用逗號連接 |
addQueryPrefix | false | 序列化後的字符串開頭是否自動添加 ? |
delimiter | ‘&’ | 序列化的字符串參數之間的連接符 |
sort | function (a, b){} | 序列化時參數排序方法 |
filter | function(key, value){} / [] | 只序列化滿足filter的參數 |
方法參數
1. parse(string, options)
1.1 解析爲對象
- qs支持在查詢字符串中創建嵌套對象,方法是通過[]將子建名稱括起來
qs.parse('foo[bar]=baz') // {foo: {bar: 'baz'}}
- 支持嵌套多層,默認情況下qs只會解析5層,超過5層的會被作爲一個key
import assert from 'assert'
var expected = {
a: {
b: {
c: {
d: {
e: {
f: {
'[g][h][i]': 'j'
}
}
}
}
}
}
};
var string = 'a[b][c][d][e][f][g][h][i]=j';
assert.deepEqual(qs.parse(string), expected);
- options
- depth
number 默認 5
該屬性可以控制qs解析時,允許的嵌套層數
qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
// { a: { b: { '[c][d][e][f][g][h][i]': j } }
- plainObjects
boolean, 默認false
當傳入該參數時,解析後生成的對象是相當於通過Object.create(null)創建的對象,所以需要注意解析後生成的對象,prototype屬性是不存在的,可以給他們設置任意值
qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
// { a: { hasOwnProperty: 'b' } }
- allowPrototypes
boolean, 默認false
默認情況下,修改Object原型屬性的操作是會被忽略的,如果想保留其他原型屬性,只修改某一個字段,可以使用allowPrototypes屬性來控制,但是要小心使用(如果用到了一個被改寫過的屬性可能會有問題)
qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
// { a: { hasOwnProperty: 'b' } }
URI編碼過的字符也可以解析
import assert from 'assert'
assert.deepEqual(qs.parse('a%5Bb%5D=c'), {
a: { b: 'c' }
});
- parameterLimit
number 默認1000
qs解析時,默認解析1000個參數,通過該參數可以控制解析的參數個數,超過的會被忽略掉
qs.parse('a=b&c=d', { parameterLimit: 1 });
// { a: b }
- ignoreQueryPrefix
boolean, 默認false
查詢參數一般以?開頭,默認會被解析到第一個參數的key中,爲了避免把?解析到對象,可以使用該參數控制,從而忽略查詢參數前綴
var protoObject = qs.parse('?a[s]=b&c=3') // { ?a: { s: b }, c: 3}
var protoObject = qs.parse('?a[s]=b&c=3', { ignoreQueryPrefix: true }) // { a: { s: b }, c: 3}
- delimiter
string | regex
默認qs通過&來分割解析字符串,可以通過delimiter來指定自定義分割符
qs.parse('a=b;c=d', { delimiter: ';' }); // { a: 'b', c: 'd' }
delimiter可以通過正則表達式來制定多個,只要解析過程中遇到制定分割符就進行分割
qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ })// { a: 'b', c: 'd', e: 'f' }
- allowDots
boolean, 默認false
當字符串中出現 . 的時候,不解析到對象的key中,而是作爲嵌套子對象來處理
var protoObject = qs.parse('?a.s.s.d=b&c=3', { ignoreQueryPrefix: true, allowDots: true })
{ a: { s: { s: { d: 'b' } } }, c:3 }
- charset
編碼格式, 默認utf-8
1.2 解析爲數組
ajax請求中,發送x-www-form-urlencoded格式數據時,如果參數是數組,例如a=[‘b’,‘c’]會被默認解析成a[]=b&a[]=c
- qs可以根據[]來解析數組
qs.parse('a[]=b&a[]=c'); // { a: ['b', 'c'] }
- 支持指定索引
qs.parse('a[1]=c&a[0]=b');
注意: []裏的值是數字時才能當作數組處理,否則會處理爲對象;當索引不連續時,qs會自動把創建出的稀疏數組壓縮,僅保留有值的順序
- 字符串也是值,會保留
qs.parse('a[]=&a[]=c') // { a: ['', 'c'] }
qs.parse('a[0]=b&a[1]=&a[2]=c') // { a: ['b', '', 'c'] }
qs默認數組長度只到20, 所以當指定的索引超過20時,整個屬性會被當作對象處理
- 如果指定的索引有數字也有字母的情況下,qs也會按照對象格式來解析
qs.parse('a[0]=b&a[b]=c') // { a: { '0': 'b', b: 'c' } }
- qs支持根據,來解析成數組
qs.parse('a=b,c', { comma: true }) // { a: ['b', 'c'] }
- 支持解析爲對象數組, 當連續兩個[]中都是數字時,會按照稀疏數組來處理
qs.parse('a[][b]=c') // a: [{ b: 'c' }]
qs.parse('a[][b][0][1]=c') // a: [{ b: ['c'] }] qs認爲0出索引沒有值,當作稀疏數組來處理
- options
- arrayLimit
number 默認20
指定允許解析的數組的最大索引
// 索引超過指定的最大值
qs.parse('a[1]=b&a[2]=1', { arrayLimit: 0 }) // { a: { 1: 'b', 2: 1 } }
qs.parse('a[1]=b&a[2]=1', { arrayLimit: 2 }) // { a: ['b', 1] }
- parseArrays
boolean 默認true qs是否支持解析爲數組
// parseArrays 設爲false,不解析爲數組,全部按照對象來解析
qs.parse('a[]=b', { parseArrays: false }); // { a: { '0': 'b' } }
- comma
boolean 默認false,是否支持解析,分割符鏈接的數組,除了這樣的a={b:1},{c:d}
qs.parse('a=b,c', { comma: true })
2. stringify(object, [options])
- 對象序列化時,會默認URI編碼後輸出。
assert.equal(qs.stringify({ a: 'b' }), 'a=b');
assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
- 序列化數組參數,默認情況下序列化成以下顯式格式
qs.stringify({ a: ['b', 'c', 'd'] }); // 'a[0]=b&a[1]=c&a[2]=d'
- 通過指定options參數的indices屬性爲false可以轉成以下格式
qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
// 'a=b&a=c&a=d'
- 嵌套的對象,序列化時默認用[]表示
qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
// 'a[b][c]=d&a[b][e]=f'
- 空字符串和空對象的序列化結果
// 值爲空字符串時如下
assert.equal(qs.stringify({ a: '' }), 'a=');
// 控對象空數組如下
assert.equal(qs.stringify({ a: [] }), '');
assert.equal(qs.stringify({ a: {} }), '');
assert.equal(qs.stringify({ a: [{}] }), '');
assert.equal(qs.stringify({ a: { b: []} }), '');
assert.equal(qs.stringify({ a: { b: {}} }), '');
值爲null時會當作空字符串處理
值爲undefined時會忽略
- options
- encode
是否編碼輸出 - encodeValuesOnly
是否只對值進行編碼 - encoder
自定義編碼方法, 當encode爲false時無效
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) {
// Passed in values `a`, `b`, `c`
return // Return encoded string
}})
對應的解碼方法
var decoded = qs.parse('x=z', { decoder: function (str) {
// Passed in values `x`, `z`
return // Return decoded string
}})
可以對key, value指定不同的編碼方法
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) {
if (type === 'key') {
return // Encoded key
} else if (type === 'value') {
return // Encoded value
}
}})
- indices
是否顯式序列化數組 - arrayFormat
可以通過指定該值來控制數組序列化輸出
qs.stringify({ a: ['b', 'c']}, { arrayFormat: 'indices' }) //顯示數組索引 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c']}, { arrayFormat: 'brackets' })
// 只用中括號表示 'a[]=b&a[]=c'
qs.stringify({ a: ['b', 'c']}, { arrayFormat: 'repeat' })
// 重複顯示key 'a=b&a=c'
qs.stringify({ a: ['b', 'c']}, { arrayFormat: 'comma' })
// 用都好連接 'a=b,c'
- allowDots
嵌套的子對象屬性表示方法, true表示用.連接, 否則默認的[]連接 - addQueryPrefix
對象序列化爲查詢字符串時,默認開頭不帶?, 通過設置該屬性爲true,字符串會自動?開頭 - delimiter
指定對象序列化時的連接符 - sort
指定參數key的排序方法
// 按照字母順序排序
function alphabeticalSort(a, b) {
return a.localeCompare(b);
}
assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y')
- filter
可以時函數或者數組
函數時接受(key, value)兩個參數,分別表示參數的鍵, 值
qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2, 'e'], encode: false })
// a[0]=b&a[2]=d&e=f
通過filter數組來篩選需要序列化進查詢字符串的key