debugjavascriptMinor
Is this query-string parser bug-free?
Viewed 0 times
thisbugfreeparserquerystring
Problem
I tried to implement a definitive, reliable URL query string parser that handles every corner case:
What do you think - did I miss something?
It returns an object of arrays for parsed URLs with query strings and
I used this in an answer over at SO.
- it tries to be efficient by avoiding regex
- it takes full URLs or just query strings (as long as the query string begins with a question mark)
- it ignores the hash value
- it handles multiple equal parameter names
- it handles parameter names that equal built-in JavaScript methods and keywords
What do you think - did I miss something?
function parseURLParams(url) {
if (url === null) return;
var queryStart = url.indexOf("?") + 1,
queryEnd = url.indexOf("#") + 1 || url.length + 1,
query = url.slice(queryStart, queryEnd - 1);
if (query === url || query === "") return;
var params = {},
nvPairs = query.replace(/\+/g, " ").split("&");
for (var i=0; i<nvPairs.length; i++) {
var nv = nvPairs[i],
eq = nv.indexOf("=") + 1 || nv.length + 1,
n = decodeURIComponent( nv.slice(0, eq - 1) ),
v = decodeURIComponent( nv.slice(eq) );
if ( n !== "" ) {
if ( !Object.prototype.hasOwnProperty.call(params, n) ) {
params[n] = [];
}
params[n].push(v);
}
}
return params;
}It returns an object of arrays for parsed URLs with query strings and
undefined if a query string could not be identified.I used this in an answer over at SO.
Solution
Is it bug free? No.
These two corner-cases have been missed:
The first may well count as malformed URL, but Chrome handles it and pass through == unencoded in
The second problem's just pedantic really. You could try and work around it using
I guess you'd then have to resort to returning an array of arrays rather than an object. i.e. each element of the array returned would either be
These two corner-cases have been missed:
- parameter values containing '=', i.e. 'example.com?foo==bar' (double equals) or '?foo=k=v'
- cannot handle parameters called 'toString' and 'valueOf' (amongst others.)
The first may well count as malformed URL, but Chrome handles it and pass through == unencoded in
location.search. To handle this, go back to basic indexOf usage.The second problem's just pedantic really. You could try and work around it using
!params.hasOwnProperty(n) instead of !(n in params), but you'll still get stuck if someone passes a parameter called hasOwnProperty. The only way I see around this is to fall back to some dire array-based collection populated something like:var keys = [], params = [];
for (...) {
var n = ..., v = ...;
var i = keys.indexOf(n);
if (i >= 0) {
if (!(params[i] instanceof Array)) {
params[i] = [params[i]];
}
params.push(v);
} else {
params[i] = v;
keys.push(n);
}
}I guess you'd then have to resort to returning an array of arrays rather than an object. i.e. each element of the array returned would either be
[key, value] or [key, [values]], although client might find it easier to work with if you returned something like [key, value1, value2, ...] (which caters nicely for properties without values.)Code Snippets
var keys = [], params = [];
for (...) {
var n = ..., v = ...;
var i = keys.indexOf(n);
if (i >= 0) {
if (!(params[i] instanceof Array)) {
params[i] = [params[i]];
}
params.push(v);
} else {
params[i] = v;
keys.push(n);
}
}Context
StackExchange Code Review Q#2924, answer score: 2
Revisions (0)
No revisions yet.