Browse Source

Allow callers to disable PHP/Rails style parameter mungeing in querystring.stringify

v0.7.4-release
Thomas Lee 15 years ago
committed by Ryan Dahl
parent
commit
a63ce5cd72
  1. 30
      doc/api.markdown
  2. 10
      lib/querystring.js
  3. 14
      test/simple/test-querystring.js

30
doc/api.markdown

@ -2459,7 +2459,7 @@ Take a base URL, and a href URL, and resolve them as a browser would for an anch
This module provides utilities for dealing with query strings. It provides the following methods: This module provides utilities for dealing with query strings. It provides the following methods:
### querystring.stringify(obj, sep='&', eq='=') ### querystring.stringify(obj, sep='&', eq='=', munge=true)
Serialize an object to a query string. Optionally override the default separator and assignment characters. Serialize an object to a query string. Optionally override the default separator and assignment characters.
Example: Example:
@ -2468,6 +2468,32 @@ Example:
// returns // returns
'foo=bar' 'foo=bar'
querystring.stringify({foo: 'bar', baz: 'bob'}, ';', ':')
// returns
'foo:bar;baz:bob'
By default, this function will perform PHP/Rails-style parameter mungeing for arrays and objects used as
values within `obj`.
Example:
querystring.stringify({foo: 'bar', foo: 'baz', foo: 'boz'})
// returns
'foo[]=bar&foo[]=baz&foo[]=boz'
querystring.stringify({foo: {bar: 'baz'}})
// returns
'foo[bar]=baz'
If you wish to disable the array mungeing (e.g. when generating parameters for a Java servlet), you
can set the `munge` argument to `false`.
Example:
querystring.stringify({foo: 'bar', foo: 'baz', foo: 'boz'}, '&', '=', false)
// returns
'foo=bar&foo=baz&foo=boz'
Note that when `munge` is `false`, parameter names with object values will still be munged.
### querystring.parse(str, sep='&', eq='=') ### querystring.parse(str, sep='&', eq='=')
Deserialize a query string to an object. Optionally override the default separator and assignment characters. Deserialize a query string to an object. Optionally override the default separator and assignment characters.
@ -2478,6 +2504,8 @@ Deserialize a query string to an object. Optionally override the default separa
, 'b': 'c' , 'b': 'c'
} }
This function can parse both munged and unmunged query strings (see `stringify` for details).
### querystring.escape ### querystring.escape
The escape function used by `querystring.stringify`, provided so that it could be overridden if necessary. The escape function used by `querystring.stringify`, provided so that it could be overridden if necessary.

10
lib/querystring.js

@ -21,10 +21,12 @@ var stack = [];
* @param obj {Variant} any arbitrary value to convert to query string * @param obj {Variant} any arbitrary value to convert to query string
* @param sep {String} (optional) Character that should join param k=v pairs together. Default: "&" * @param sep {String} (optional) Character that should join param k=v pairs together. Default: "&"
* @param eq {String} (optional) Character that should join keys to their values. Default: "=" * @param eq {String} (optional) Character that should join keys to their values. Default: "="
* @param munge {Boolean} (optional) Indicate whether array/object params should be munged, PHP/Rails-style. Default: true
* @param name {String} (optional) Name of the current key, for handling children recursively. * @param name {String} (optional) Name of the current key, for handling children recursively.
* @static * @static
*/ */
QueryString.stringify = function (obj, sep, eq, name) { QueryString.stringify = function (obj, sep, eq, munge, name) {
munge = typeof(munge) == "undefined" ? true : munge;
sep = sep || "&"; sep = sep || "&";
eq = eq || "="; eq = eq || "=";
if (isA(obj, null) || isA(obj, undefined) || typeof(obj) === 'function') { if (isA(obj, null) || isA(obj, undefined) || typeof(obj) === 'function') {
@ -37,9 +39,9 @@ QueryString.stringify = function (obj, sep, eq, name) {
} }
if (isA(obj, [])) { if (isA(obj, [])) {
var s = []; var s = [];
name = name+'[]'; name = name+(munge ? '[]' : '');
for (var i = 0, l = obj.length; i < l; i ++) { for (var i = 0, l = obj.length; i < l; i ++) {
s.push( QueryString.stringify(obj[i], sep, eq, name) ); s.push( QueryString.stringify(obj[i], sep, eq, munge, name) );
} }
return s.join(sep); return s.join(sep);
} }
@ -59,7 +61,7 @@ QueryString.stringify = function (obj, sep, eq, name) {
for (var i = 0, l = keys.length; i < l; i++) { for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i]; var key = keys[i];
var n = begin + key + end; var n = begin + key + end;
s.push(QueryString.stringify(obj[key], sep, eq, n)); s.push(QueryString.stringify(obj[key], sep, eq, munge, n));
} }
stack.pop(); stack.pop();

14
test/simple/test-querystring.js

@ -58,6 +58,16 @@ var qsWeirdObjects = [
]; ];
} }
var qsNoMungeTestCases = [
["", {}],
["foo=bar&foo=baz", {"foo": ["bar", "baz"]}],
["blah=burp", {"blah": "burp"}],
["gragh=1&gragh=3&goo=2", {"gragh": ["1", "3"], "goo": "2"}],
["frappucino=muffin&goat%5B%5D=scone&pond=moose",
{"frappucino": "muffin", "goat[]": "scone", "pond": "moose"}],
["obj%5Btrololol%5D=yes&obj%5Blololo%5D=no", {"obj": {"trololol": "yes", "lololo": "no"}}],
];
// test that the canonical qs is parsed properly. // test that the canonical qs is parsed properly.
qsTestCases.forEach(function (testCase) { qsTestCases.forEach(function (testCase) {
assert.deepEqual(testCase[2], qs.parse(testCase[0])); assert.deepEqual(testCase[2], qs.parse(testCase[0]));
@ -73,6 +83,10 @@ qsWeirdObjects.forEach(function (testCase) {
assert.deepEqual(testCase[2], qs.parse(testCase[1])); assert.deepEqual(testCase[2], qs.parse(testCase[1]));
}); });
qsNoMungeTestCases.forEach(function (testCase) {
assert.deepEqual(testCase[0], qs.stringify(testCase[1], "&", "=", false));
});
// test the nested qs-in-qs case // test the nested qs-in-qs case
var f = qs.parse("a=b&q=x%3Dy%26y%3Dz"); var f = qs.parse("a=b&q=x%3Dy%26y%3Dz");
f.q = qs.parse(f.q); f.q = qs.parse(f.q);

Loading…
Cancel
Save