qs是一个流行的查询参数序列化和解析库。可以将一个普通的object序列化成一个查询字符串,或者反过来将一个查询字符串解析成一个object,而且支持复杂的嵌套。它上手很容易:
Qs.parse('x[]=1') // {x: ['1']}
Qs.stringify({x: [1]}) // x%5B0%5D=1
qs的两个方法都接受一个可选的第二参数,可以让我们对结果进行配置,个人觉得比较有用的有以下几个:
ignoreQueryPrefix和addQueryPrefix
ignoreQueryPrefix这个参数可以自动帮我们过滤掉location.search前面的❓,然后再解析,addQueryPrefix
设为true可以在序列化的时候给我们加上?
// 解析
Qs.parse('?x=1') // {?x: "1"}
Qs.parse('?x=1', {ignoreQueryPrefix: true}) // {x: "1"}
// 序列化
Qs.stringify({x: "1"}) // x=1
Qs.parse({x: "1"}, {addQueryPrefix: true}) // ?x=1
数组解析和序列化
数组序列化有几种方式:indices
, brackets
, repeat
, comma
,用来控制字符串的生成格式。来看下面的例子:
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' })
// 'a=b&a=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
// 'a=b,c'
上面的四种方式,序列化得到的结果越来越精简,但是当面对嵌套数组时,却会导致不同程度的信息丢失,而且丢失的越来越严重。以四种方式对{ a: [['b'], 'c'] }
stringify 再 parse为例:
qs.parse(qs.stringify({ a: [['b'], 'c'] }, { arrayFormat: 'indices' })) // { a: [['b'], 'c'] }
qs.parse(qs.stringify({ a: [['b'], 'c'] }, { arrayFormat: 'brackets' })) // {a: ["b", "c"]}
qs.parse(qs.stringify({ a: [['b'], 'c'] }, { arrayFormat: 'repeat' })) // {a: ["b", "c"]}
qs.parse(qs.stringify({ a: [['b'], 'c'] }, { arrayFormat: 'comma' })) // {a: "b,c"}
所以当数据里有嵌套时最好使用indices
模式,好在这也是默认模式。
delimiter
delimiter可以控制将哪种字符作为分隔符,由于cookie的格式是使用;
来分隔,一个有用的例子是用来解析cookie:
document.cookie // "_ga=GA1.2.806176131.1570244607; _jsuid=1335121594; _gid=GA1.2.1453554609.1575990858"
Qs.parse(document.cookie, {delimiter:'; '})
数字类型的解析
正如我们在第一个例子看到的那样,我们把一个数字序列化再还原,得到的并不是一个数字,而是一个字符串:
Qs.parse(Qs.stringify({x:1})) // {x: '1'}
如果希望解析出来依旧是数字,可以参考这个issue,就是写一个自定义decoder:
Qs.parse('x[0]=1', {
decoder(str, defaultEncoder, charset, type) {
if (/^(d+|d*.d+)$/.test(str)) {
return parseFloat(str)
}
return str
}
})
或者再加上一个解析中文的功能:
if (/^%[A-Za-z0-9+/]/.test(str)) {
return decodeURIComponent(str)
}
本文完