npm qs模块使用详解
本文基本使用谷歌翻译加上自己的理解,权当加深记忆。
npm
简介
qs是一个增加了一些安全性的查询字符串解析和序列化字符串的库。
主要维护者:JordanHarband
最初创建者和维护者:TJHolowaychuk
用法
varqs=require('qs'); varassert=require('assert'); varobj=qs.parse('a=c'); assert.deepEqual(obj,{a:'c'}); varstr=qs.stringify(obj); assert.equal(str,'a=c');
解析对象
qs.parse(string,[options]);
qs允许在查询字符串中使用[]的方式创建嵌套的对象。例如,字符串'foo[bar]=baz'可以转换为:
assert.deepEqual(qs.parse('foo[bar]=baz'),{ foo:{ bar:'baz' } });
WhenusingtheplainObjectsoptiontheparsedvalueisreturnedasanullobject,createdviaObject.create(null)andassuchyoushouldbeawarethatprototypemethodswillnotexistonitandausermaysetthosenamestowhatevervaluetheylike:
varnullObject=qs.parse('a[hasOwnProperty]=b',{plainObjects:true}); assert.deepEqual(nullObject,{a:{hasOwnProperty:'b'}});
Bydefaultparametersthatwouldoverwritepropertiesontheobjectprototypeareignored,ifyouwishtokeepthedatafromthosefieldseitheruseplainObjectsasmentionedabove,orsetallowPrototypestotruewhichwillallowuserinputtooverwritethoseproperties.WARNINGItisgenerallyabadideatoenablethisoptionasitcancauseproblemswhenattemptingtousethepropertiesthathavebeenoverwritten.Alwaysbecarefulwiththisoption.
varprotoObject=qs.parse('a[hasOwnProperty]=b',{allowPrototypes:true}); assert.deepEqual(protoObject,{a:{hasOwnProperty:'b'}});
也可以解析URI编码:
assert.deepEqual(qs.parse('a%5Bb%5D=c'),{ a:{b:'c'} });
还可以像这样嵌套对象:'foo[bar][baz]=foobarbaz':
assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'),{ foo:{ bar:{ baz:'foobarbaz' } } });
当使用嵌套对象时,qs在默认情况下最多解析到的深度是第五层(注:从第一个方括号到算起,到第五个方括号),例如尝试解析一个这样的字符串'a[b][c][d][e][f][g][h][i]=j'将会得到以下结果:
varexpected={ a:{ b:{ c:{ d:{ e:{ f:{ '[g][h][i]':'j' } } } } } } }; varstring='a[b][c][d][e][f][g][h][i]=j'; assert.deepEqual(qs.parse(string),expected);
可以给qs.parse传递一个depth参数覆盖默认值:
vardeep=qs.parse('a[b][c][d][e][f][g][h][i]=j',{depth:1}); assert.deepEqual(deep,{a:{b:{'[c][d][e][f][g][h][i]':'j'}}});
当qs用于解析用户输入的时候,解析深度的限制有助于减轻用户的滥用行为。最好将depth设置为一个合理的尽量小的数字。
出于类似的原因,qs在默认情况下最多解析1000个参数。通过传递parameterLimit参数可以修改默认值:
varlimited=qs.parse('a=b&c=d',{parameterLimit:1}); assert.deepEqual(limited,{a:'b'});
忽略查询字符串开头的?可以使用ignoreQueryPrefix:
varprefixed=qs.parse('?a=b&c=d',{ignoreQueryPrefix:true}); assert.deepEqual(prefixed,{a:'b',c:'d'});
还可以根据自定义的分隔符来解析delimiter:
vardelimited=qs.parse('a=b;c=d',{delimiter:';'}); assert.deepEqual(delimited,{a:'b',c:'d'});
分隔符可以是正则表达式:
varregexed=qs.parse('a=b;c=d,e=f',{delimiter:/[;,]/}); assert.deepEqual(regexed,{a:'b',c:'d',e:'f'});
allowDots选项可以启用点表示法:
varwithDots=qs.parse('a.b=c',{allowDots:true}); assert.deepEqual(withDots,{a:{b:'c'}});
解析数组
qs也可以用[]解析数组:
varwithArray=qs.parse('a[]=b&a[]=c'); assert.deepEqual(withArray,{a:['b','c']});
可以指定数组索引:
varwithIndexes=qs.parse('a[1]=c&a[0]=b'); assert.deepEqual(withIndexes,{a:['b','c']});
请注意,如果想要将字符串解析成数组而不是对象,那么[]之间的值必须是一个数字。在创建具有特定索引的数组时,qs会将稀疏数组压缩为仅保留其顺序的现有值:
varnoSparse=qs.parse('a[1]=b&a[15]=c'); assert.deepEqual(noSparse,{a:['b','c']});
空字符串也是一个值,并将被保留:
varwithEmptyString=qs.parse('a[]=&a[]=b'); assert.deepEqual(withEmptyString,{a:['','b']}); varwithIndexedEmptyString=qs.parse('a[0]=b&a[1]=&a[2]=c'); assert.deepEqual(withIndexedEmptyString,{a:['b','','c']});
qs还会限制数组最大索引为20,任何索引大于20的数组成员都将被转换为以索引为键的对象:
varwithMaxIndex=qs.parse('a[100]=b'); assert.deepEqual(withMaxIndex,{a:{'100':'b'}});
arrayLimit选项可以修改默认限制:
varwithArrayLimit=qs.parse('a[1]=b',{arrayLimit:0}); assert.deepEqual(withArrayLimit,{a:{'1':'b'}});
字符串不解析成数组,可以设置parseArrays为false
varnoParsingArrays=qs.parse('a[]=b',{parseArrays:false}); assert.deepEqual(noParsingArrays,{a:{'0':'b'}});
如果混合使用两种格式,qs会将字符串解析为对象:
varmixedNotation=qs.parse('a[0]=b&a[b]=c'); assert.deepEqual(mixedNotation,{a:{'0':'b',b:'c'}});
也可以创建元素为对象的数组:
vararraysOfObjects=qs.parse('a[][b]=c'); assert.deepEqual(arraysOfObjects,{a:[{b:'c'}]});
序列化字符串
qs.stringify(object,[options]);
默认情况下,对象序列化后进行URI编码后输出:
assert.equal(qs.stringify({a:'b'}),'a=b'); assert.equal(qs.stringify({a:{b:'c'}}),'a%5Bb%5D=c');
通过设置encode为false禁止URI编码:
varunencoded=qs.stringify({a:{b:'c'}},{encode:false}); assert.equal(unencoded,'a[b]=c');
通过设置encodeValuesOnly为true,可以禁用对key进行URI编码:
varencodedValues=qs.stringify( {a:'b',c:['d','e=f'],f:[['g'],['h']]}, {encodeValuesOnly:true} ); assert.equal(encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h');
可以通过设置encoder选项自定义编码方式(注意:当encode被设置为false的时候,不适用):
varencoded=qs.stringify({a:{b:'c'}},{encoder:function(str){ //Passedinvalues`a`,`b`,`c` return//Returnencodedstring }})
与encoder类似decoder可以用来解码:
vardecoded=qs.parse('x=z',{decoder:function(str){ //Passedinvalues`x`,`z` return//Returndecodedstring }})
ExamplesbeyondthispointwillbeshownasthoughtheoutputisnotURIencodedforclarity.PleasenotethatthereturnvaluesinthesecaseswillbeURIencodedduringrealusage.
当数组被序列化时,默认显示索引:
qs.stringify({a:['b','c','d']}); //'a[0]=b&a[1]=c&a[2]=d'
可以通过设置indices为false不显示索引:
qs.stringify({a:['b','c','d']},{indices:false}); //'a=b&a=c&a=d'
可以通过设置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'}) //'a=b&a=c'
对象序列化时,默认使用[]表示法:
qs.stringify({a:{b:{c:'d',e:'f'}}}); //'a[b][c]=d&a[b][e]=f'
通过设置allowDots为true修改为点表示法:
qs.stringify({a:{b:{c:'d',e:'f'}}},{allowDots:true}); //'a.b.c=d&a.b.e=f'
空字符串和null值将被省略,但是=会保留:
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:{}}}),'');
值为undefined的属性将会被完全忽略:
assert.equal(qs.stringify({a:null,b:undefined}),'a=');
addQueryPrefix设置为true可以在查询字符串前面加?:
assert.equal(qs.stringify({a:'b',c:'d'},{addQueryPrefix:true}),'?a=b&c=d');
分隔符也可以设置:
assert.equal(qs.stringify({a:'b',c:'d'},{delimiter:';'}),'a=b;c=d');
如果只是序列化日期对象,可以使用serializeDate选项:
vardate=newDate(7); assert.equal(qs.stringify({a:date}),'a=1970-01-01T00:00:00.007Z'.replace(/:/g,'%3A')); assert.equal( qs.stringify({a:date},{serializeDate:function(d){returnd.getTime();}}), 'a=7' );
可以使用sort选项来修改键的顺序:
functionalphabeticalSort(a,b){ returna.localeCompare(b); } assert.equal(qs.stringify({a:'c',z:'y',b:'f'},{sort:alphabeticalSort}),'a=c&b=f&z=y');
最后,可以使用filter选项过滤序列化输出的键。如果给filter传递一个函数,每个键调用一次该函数并用返回的值替换原来值。如果给filter传递一个数组,它将用于选择对象的key和数组的索引:
functionfilterFunc(prefix,value){ if(prefix=='b'){ //Returnan`undefined`valuetoomitaproperty. return; } if(prefix=='e[f]'){ returnvalue.getTime(); } if(prefix=='e[g][0]'){ returnvalue*2; } returnvalue; } qs.stringify({a:'b',c:'d',e:{f:newDate(123),g:[2]}},{filter:filterFunc}); //'a=b&c=d&e[f]=123&e[g][0]=4' qs.stringify({a:'b',c:'d',e:'f'},{filter:['a','e']}); //'a=b&e=f' qs.stringify({a:['b','c','d'],e:'f'},{filter:['a',0,2]}); //'a[0]=b&a[2]=d'
处理null值
默认情况下,null值被视为空对象:
varwithNull=qs.stringify({a:null,b:''}); assert.equal(withNull,'a=&b=');
解析字符串的时候并不会区分参数有没有等号,没有值的话都会解析为空字符串:
varequalsInsensitive=qs.parse('a&b='); assert.deepEqual(equalsInsensitive,{a:'',b:''});
要想区分空字符串和null值可以使用strictNullHandling选项,序列化后的null值没有=
varstrictNull=qs.stringify({a:null,b:''},{strictNullHandling:true}); assert.equal(strictNull,'a&b=');
要解析不带=的值返回null可以使用strictNullHandling选项:
varparsedStrictNull=qs.parse('a&b=',{strictNullHandling:true}); assert.deepEqual(parsedStrictNull,{a:null,b:''});
想要完全跳过值为null的键不解析,可以使用skipNulls选项:
varnullsSkipped=qs.stringify({a:'b',c:null},{skipNulls:true}); assert.equal(nullsSkipped,'a=b');
处理特殊字符集:
默认情况下,字符的编码和解码在utf-8中完成。如果希望将查询字符串编码为不同的字符集(i.e.ShiftJIS),您可以使用qs-iconv库:
varencoder=require('qs-iconv/encoder')('shift_jis'); varshiftJISEncoded=qs.stringify({a:'こんにちは!'},{encoder:encoder}); assert.equal(shiftJISEncoded,'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I');
这也适用于解码查询字符串:
vardecoder=require('qs-iconv/decoder')('shift_jis'); varobj=qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I',{decoder:decoder}); assert.deepEqual(obj,{a:'こんにちは!'});
RFC3986andRFC1738spaceencoding
RFC3986usedasdefaultoptionandencodes''to%20whichisbackwardcompatible.Inthesametime,outputcanbestringifiedasperRFC1738with''equalto‘+'.
assert.equal(qs.stringify({a:'bc'}),'a=b%20c'); assert.equal(qs.stringify({a:'bc'},{format:'RFC3986'}),'a=b%20c'); assert.equal(qs.stringify({a:'bc'},{format:'RFC1738'}),'a=b+c');
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。