Skip to content

Commit

Permalink
Allow callers to disable PHP/Rails style parameter mungeing in querys…
Browse files Browse the repository at this point in the history
…tring.stringify
  • Loading branch information
Thomas Lee authored and ry committed Apr 28, 2010
1 parent 039d13b commit a63ce5c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
30 changes: 29 additions & 1 deletion doc/api.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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:

### 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.
Example:
Expand All @@ -2468,6 +2468,32 @@ Example:
// returns
'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='=')

Deserialize a query string to an object. Optionally override the default separator and assignment characters.
Expand All @@ -2478,6 +2504,8 @@ Deserialize a query string to an object. Optionally override the default separa
, 'b': 'c'
}

This function can parse both munged and unmunged query strings (see `stringify` for details).

### querystring.escape

The escape function used by `querystring.stringify`, provided so that it could be overridden if necessary.
Expand Down
10 changes: 6 additions & 4 deletions lib/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ var stack = [];
* @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 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.
* @static
*/
QueryString.stringify = function (obj, sep, eq, name) {
QueryString.stringify = function (obj, sep, eq, munge, name) {
munge = typeof(munge) == "undefined" ? true : munge;
sep = sep || "&";
eq = eq || "=";
if (isA(obj, null) || isA(obj, undefined) || typeof(obj) === 'function') {
Expand All @@ -37,9 +39,9 @@ QueryString.stringify = function (obj, sep, eq, name) {
}
if (isA(obj, [])) {
var s = [];
name = name+'[]';
name = name+(munge ? '[]' : '');
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);
}
Expand All @@ -59,7 +61,7 @@ QueryString.stringify = function (obj, sep, eq, name) {
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
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();
Expand Down
14 changes: 14 additions & 0 deletions test/simple/test-querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
qsTestCases.forEach(function (testCase) {
assert.deepEqual(testCase[2], qs.parse(testCase[0]));
Expand All @@ -73,6 +83,10 @@ qsWeirdObjects.forEach(function (testCase) {
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
var f = qs.parse("a=b&q=x%3Dy%26y%3Dz");
f.q = qs.parse(f.q);
Expand Down

0 comments on commit a63ce5c

Please sign in to comment.