Skip to content

Instantly share code, notes, and snippets.

@alisey
Last active December 11, 2015 05:28
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alisey/4552101 to your computer and use it in GitHub Desktop.
Save alisey/4552101 to your computer and use it in GitHub Desktop.
Parsing URL query string in JavaScript.
// Examples:
// parseQueryString('a=1&a=2') => {a: '2'}
// parseQueryString('a=1', true) => {a: ['1']}
// parseQueryString('a=1&a=2', true) => {a: ['1', '2']}
// parseQueryString('a[][]=1&a[][]=2', true) => {'a[][]': ['1', '2']}
// parseQueryString('?a;b#c') => {'?a': '', 'b#c': ''}
function parseQueryString(query, groupByName) {
var parsed, hasOwn, pairs, pair, name, value;
if (typeof query != 'string') {
throw 'Invalid input';
}
parsed = {};
hasOwn = parsed.hasOwnProperty;
query = query.replace(/\+/g, ' ');
pairs = query.split(/[&;]/);
for (var i = 0; i < pairs.length; i++) {
pair = pairs[i].match(/^([^=]*)=?(.*)/);
if (pair[1]) {
try {
name = decodeURIComponent(pair[1]);
value = decodeURIComponent(pair[2]);
} catch(e) {
throw 'Invaid %-encoded sequence';
}
if (!groupByName) {
parsed[name] = value;
} else if (hasOwn.call(parsed, name)) {
parsed[name].push(value);
} else {
parsed[name] = [value];
}
}
}
return parsed;
}
// qUnit Tests
test("parseQueryString keyval format", function() {
deepEqual(parseQueryString('a=1'), {'a': '1'});
deepEqual(parseQueryString('a='), {'a': ''});
deepEqual(parseQueryString('a'), {'a': ''});
deepEqual(parseQueryString('='), {});
deepEqual(parseQueryString(''), {});
deepEqual(parseQueryString('=1'), {});
deepEqual(parseQueryString('==='), {});
deepEqual(parseQueryString('a==1'), {'a': '=1'});
deepEqual(parseQueryString('a%3D1'), {'a=1' : ''});
});
test("parseQueryString pair separator", function() {
deepEqual(parseQueryString('a=1&b=1'), {a: '1', b: '1'});
// http://www.w3.org/TR/1999/REC-html401-19991224/appendix/notes.html#h-B.2.2
deepEqual(parseQueryString('a=1;b=1'), {a: '1', b: '1'});
});
test("parseQueryString special characters", function() {
deepEqual(parseQueryString('&&&=1'), {});
deepEqual(parseQueryString('???=1'), {'???': '1'});
deepEqual(parseQueryString('###=1'), {'###': '1'});
deepEqual(parseQueryString('a+%2B+b=1'), {'a + b': '1'});
deepEqual(parseQueryString("\u0020\r\n\t=1"), {"\u0020\r\n\t": '1'});
deepEqual(parseQueryString('%C2%A9=%C2%A9'), {'©': '©'});
deepEqual(parseQueryString('привет=пока'), {'привет': 'пока'});
});
test("parseQueryString lists and duplicates", function() {
deepEqual(parseQueryString('a=1&a=2'), {'a': '2'});
deepEqual(parseQueryString('a=1', true), {'a': ['1']});
deepEqual(parseQueryString('a=1&a=2', true), {'a': ['1', '2']});
deepEqual(parseQueryString('a[]b=1', true), {'a[]b': ['1']});
deepEqual(parseQueryString('a[=1', true), {'a[': ['1']});
deepEqual(parseQueryString('a[]=1&a[]=1', true), {'a[]': ['1', '1']});
deepEqual(parseQueryString('a[][]=1&a[][]=1', true), {'a[][]': ['1', '1']});
deepEqual(parseQueryString('a[8][0]=1&a[8][1]=1', true),
{'a[8][0]': ['1'], 'a[8][1]': ['1']});
});
test("parseQueryString built-in property override", function() {
deepEqual(parseQueryString('hasOwnProperty=1'), {'hasOwnProperty': '1'});
deepEqual(parseQueryString('toString=1'), {'toString': '1'});
});
test("parseQueryString exceptions", function() {
throws(function() { parseQueryString('%C2%79'); },
'Invalid UTF-8 sequence throws an exception');
throws(function() { parseQueryString(null); },
'Input data is a string');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment