qs—对象序列化为查询参数和URL解析成对象的库

安装

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 解析为对象

  1. qs支持在查询字符串中创建嵌套对象,方法是通过[]将子建名称括起来
qs.parse('foo[bar]=baz') // {foo: {bar: 'baz'}}
  1. 支持嵌套多层,默认情况下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
  1. 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 } }
  1. plainObjects
    boolean, 默认false
    当传入该参数时,解析后生成的对象是相当于通过Object.create(null)创建的对象,所以需要注意解析后生成的对象,prototype属性是不存在的,可以给他们设置任意值
qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
// { a: { hasOwnProperty: 'b' } }
  1. 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' }
});
  1. parameterLimit
    number 默认1000
    qs解析时,默认解析1000个参数,通过该参数可以控制解析的参数个数,超过的会被忽略掉
qs.parse('a=b&c=d', { parameterLimit: 1 });
// { a: b }
  1. 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}
  1. 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' }
  1. 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 }
  1. charset
    编码格式, 默认utf-8

1.2 解析为数组

ajax请求中,发送x-www-form-urlencoded格式数据时,如果参数是数组,例如a=[‘b’,‘c’]会被默认解析成a[]=b&a[]=c

  1. qs可以根据[]来解析数组
qs.parse('a[]=b&a[]=c'); // { a: ['b', 'c'] }
  1. 支持指定索引
qs.parse('a[1]=c&a[0]=b');

注意: []里的值是数字时才能当作数组处理,否则会处理为对象;当索引不连续时,qs会自动把创建出的稀疏数组压缩,仅保留有值的顺序

  1. 字符串也是值,会保留
qs.parse('a[]=&a[]=c') // { a: ['', 'c'] }

qs.parse('a[0]=b&a[1]=&a[2]=c') // { a: ['b', '', 'c'] }

qs默认数组长度只到20, 所以当指定的索引超过20时,整个属性会被当作对象处理

  1. 如果指定的索引有数字也有字母的情况下,qs也会按照对象格式来解析
qs.parse('a[0]=b&a[b]=c') // { a: { '0': 'b', b: 'c' } }
  1. qs支持根据,来解析成数组
qs.parse('a=b,c', { comma: true }) // { a: ['b', 'c'] }
  1. 支持解析为对象数组, 当连续两个[]中都是数字时,会按照稀疏数组来处理
qs.parse('a[][b]=c') // a: [{ b: 'c' }]
qs.parse('a[][b][0][1]=c') // a: [{ b: ['c'] }] qs认为0出索引没有值,当作稀疏数组来处理

  • options
  1. 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] }
  1. parseArrays
    boolean 默认true qs是否支持解析为数组
// parseArrays 设为false,不解析为数组,全部按照对象来解析
qs.parse('a[]=b', { parseArrays: false }); // { a: { '0': 'b' } }
  1. comma
    boolean 默认false,是否支持解析,分割符链接的数组,除了这样的a={b:1},{c:d}
qs.parse('a=b,c', { comma: true })


2. stringify(object, [options])

  1. 对象序列化时,会默认URI编码后输出。
assert.equal(qs.stringify({ a: 'b' }), 'a=b');
assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
  1. 序列化数组参数,默认情况下序列化成以下显式格式
qs.stringify({ a: ['b', 'c', 'd'] }); // 'a[0]=b&a[1]=c&a[2]=d'
  1. 通过指定options参数的indices属性为false可以转成以下格式
qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
// 'a=b&a=c&a=d'
  1. 嵌套的对象,序列化时默认用[]表示
qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
// 'a[b][c]=d&a[b][e]=f'
  1. 空字符串和空对象的序列化结果
// 值为空字符串时如下
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
  1. encode
    是否编码输出
  2. encodeValuesOnly
    是否只对值进行编码
  3. 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
    }
}})
  1. indices
    是否显式序列化数组
  2. 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'
  1. allowDots
    嵌套的子对象属性表示方法, true表示用.连接, 否则默认的[]连接
  2. addQueryPrefix
    对象序列化为查询字符串时,默认开头不带?, 通过设置该属性为true,字符串会自动?开头
  3. delimiter
    指定对象序列化时的连接符
  4. 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')
  1. 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

发布了66 篇原创文章 · 获赞 13 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/haoyanyu_/article/details/103799703