Browse Source

querystring: custom encode and decode

Not all querystring are utf-8 encoding, make querystring can be used
to encode / decode `non-utf8` encoding string if necessary.

Signed-off-by: Timothy J Fontaine <tjfontaine@gmail.com>
archived-io.js-v0.10
fengmk2 11 years ago
committed by Timothy J Fontaine
parent
commit
4729202d1e
  1. 22
      doc/api/querystring.markdown
  2. 23
      lib/querystring.js
  3. 19
      test/simple/test-querystring.js

22
doc/api/querystring.markdown

@ -7,12 +7,15 @@
This module provides utilities for dealing with query strings.
It provides the following methods:
## querystring.stringify(obj, [sep], [eq])
## querystring.stringify(obj, [sep], [eq], [options])
Serialize an object to a query string.
Optionally override the default separator (`'&'`) and assignment (`'='`)
characters.
Options object may contain `encodeURIComponent` property (`querystring.escape` by default),
it can be used to encode string with `non-utf8` encoding if necessary.
Example:
querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' })
@ -23,6 +26,13 @@ Example:
// returns
'foo:bar;baz:qux'
// Suppose gbkEncodeURIComponent function already exists,
// it can encode string with `gbk` encoding
querystring.stringify({ w: '中文', foo: 'bar' }, null, null,
{ encodeURIComponent: gbkEncodeURIComponent })
// returns
'w=%D6%D0%CE%C4&foo=bar'
## querystring.parse(str, [sep], [eq], [options])
Deserialize a query string to an object.
@ -32,12 +42,22 @@ characters.
Options object may contain `maxKeys` property (equal to 1000 by default), it'll
be used to limit processed keys. Set it to 0 to remove key count limitation.
Options object may contain `decodeURIComponent` property (`decodeURIComponent` by default),
it can be used to decode `non-utf8` encoding string if necessary.
Example:
querystring.parse('foo=bar&baz=qux&baz=quux&corge')
// returns
{ foo: 'bar', baz: ['qux', 'quux'], corge: '' }
// Suppose gbkDecodeURIComponent function already exists,
// it can decode `gbk` encoding string
querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null,
{ decodeURIComponent: gbkDecodeURIComponent })
// returns
{ w: '中文', foo: 'bar' }
## querystring.escape
The escape function used by `querystring.stringify`,

23
lib/querystring.js

@ -125,25 +125,29 @@ var stringifyPrimitive = function(v) {
};
QueryString.stringify = QueryString.encode = function(obj, sep, eq) {
QueryString.stringify = QueryString.encode = function(obj, sep, eq, options) {
sep = sep || '&';
eq = eq || '=';
if (util.isNull(obj)) {
obj = undefined;
}
var encode = QueryString.escape;
if (options && typeof options.encodeURIComponent === 'function') {
encode = options.encodeURIComponent;
}
if (util.isObject(obj)) {
return Object.keys(obj).map(function(k) {
var ks = QueryString.escape(stringifyPrimitive(k)) + eq;
var ks = encode(stringifyPrimitive(k)) + eq;
if (util.isArray(obj[k])) {
return obj[k].map(function(v) {
return ks + QueryString.escape(stringifyPrimitive(v));
return ks + encode(stringifyPrimitive(v));
}).join(sep);
} else {
return ks + QueryString.escape(stringifyPrimitive(obj[k]));
return ks + encode(stringifyPrimitive(obj[k]));
}
}).join(sep);
}
return '';
};
@ -172,6 +176,11 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
len = maxKeys;
}
var decode = decodeURIComponent;
if (options && typeof options.decodeURIComponent === 'function') {
decode = options.decodeURIComponent;
}
for (var i = 0; i < len; ++i) {
var x = qs[i].replace(regexp, '%20'),
idx = x.indexOf(eq),
@ -186,8 +195,8 @@ QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
}
try {
k = decodeURIComponent(kstr);
v = decodeURIComponent(vstr);
k = decode(kstr);
v = decode(vstr);
} catch (e) {
k = QueryString.unescape(kstr, true);
v = QueryString.unescape(vstr, true);

19
test/simple/test-querystring.js

@ -228,3 +228,22 @@ assert.equal(0xeb, b[16]);
assert.equal(0xd8, b[17]);
assert.equal(0xa2, b[18]);
assert.equal(0xe6, b[19]);
// Test custom decode
function demoDecode(str) {
return str + str;
}
assert.deepEqual(
qs.parse('a=a&b=b&c=c', null, null, { decodeURIComponent: demoDecode }),
{ aa: 'aa', bb: 'bb', cc: 'cc' });
// Test custom encode
function demoEncode(str) {
return str[0];
}
var obj = { aa: 'aa', bb: 'bb', cc: 'cc' };
assert.equal(
qs.stringify(obj, null, null, { encodeURIComponent: demoEncode }),
'a=a&b=b&c=c');

Loading…
Cancel
Save