JavaScript parse_str
Parses GET/POST/COOKIE data and sets global variables
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 4041 42 43 44 4546 47 48 49 5051 52 53 54 5556 57 58 59 6061 62 63 64 6566 67 68 69 7071 72 73 74 7576 77 78 79 8081 82 83 84 8586 87 88 89 9091 92 93 94 9596 | function parse_str (str, array){ // Parses GET/POST/COOKIE data and sets global variables // // version: 1008.1718 // discuss at: http://phpjs.org/functions/parse_str // + original by: Cagri Ekin // + improved by: Michael White (http://getsprink.com) // + tweaked by: Jack // + bugfixed by: Onno Marsman // + reimplemented by: stag019 // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: stag019 // - depends on: urldecode // + input by: Dreamer // + bugfixed by: Brett Zamir (http://brett-zamir.me) // % note 1: When no argument is specified, will put variables in global scope. // * example 1: var arr = {}; // * example 1: parse_str('first=foo&second=bar', arr); // * results 1: arr == { first: 'foo', second: 'bar' } // * example 2: var arr = {}; // * example 2: parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.', arr); // * results 2: arr == { str_a: "Jack and Jill didn't see the well." } var glue1 = '=', glue2 = '&', array2 = String(str).replace(/^&(.*)$/, '$1').replace(/^(.*)&$/, '$1').split(glue2), i, j, chr, tmp, key, value, bracket, keys, evalStr, that = this, fixStr = function (str) { return that.urldecode(str).replace(/([\\"'])/g, '\\$1').replace(/\n/g, '\\n').replace(/\r/g, '\\r'); }; if (!array) { array = this.window; } for (i = 0; i < array2.length; i++) { tmp = array2[i].split(glue1); if (tmp.length < 2) { tmp = [tmp, '']; } key = fixStr(tmp[0]); value = fixStr(tmp[1]); while (key.charAt(0) === ' ') { key = key.substr(1); } if (key.indexOf('\0') !== -1) { key = key.substr(0, key.indexOf('\0')); } if (key && key.charAt(0) !== '[') { keys = []; bracket = 0; for (j = 0; j < key.length; j++) { if (key.charAt(j) === '[' && !bracket) { bracket = j + 1; } else if (key.charAt(j) === ']') { if (bracket) { if (!keys.length) { keys.push(key.substr(0, bracket - 1)); } keys.push(key.substr(bracket, j - bracket)); bracket = 0; if (key.charAt(j + 1) !== '[') { break; } } } } if (!keys.length) { keys = [key]; } for (j = 0; j < keys[0].length; j++) { chr = keys[0].charAt(j); if (chr === ' ' || chr === '.' || chr === '[') { keys[0] = keys[0].substr(0, j) + '_' + keys[0].substr(j + 1); } if (chr === '[') { break; } } evalStr = 'array'; for (j = 0; j < keys.length; j++) { key = keys[j]; if ((key !== '' && key !== ' ') || j === 0) { key = "'" + key + "'"; } else { key = eval(evalStr + '.push([]);') - 1; } evalStr += '[' + key + ']'; if (j !== keys.length - 1 && eval('typeof ' + evalStr) === 'undefined') { eval(evalStr + ' = [];'); } } evalStr += " = '" + value + "';\n"; eval(evalStr); } }} |
Examples
» Example 1
Running
1 2 | var arr = {}; parse_str('first=foo&second=bar', arr); |
Should result in
1 | arr == { first: 'foo', second: 'bar' } |
» Example 2
Running
1 2 | var arr = {}; parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.', arr); |
Should result in
1 | arr == { str_a: "Jack and Jill didn't see the well." } |
Dependencies
In order to use this function, you also need:
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have parse_str goodness in JavaScript.
Bug report --- "TypeError: str.replace is not a function" (Copied from FireBug)
// PHPJS cannot parse the following codes, while it's possible in PHP
parse_str('&first=foo');
parse_str('first=foo&');
parse_str('&first=foo&');
@ droope: Although there are plenty open jslint issues with this function, i is actually defined and in my tests it works. What platform are you experiencing issues on?
Two things I forgot to mention:
Depends on urldecode now.
Some places I use '==' or '!=' where I could probably use '===' or '!=='. These should probably be fixed.
Well, time to bugfix myself. ;P
Looking through the PHP source I realized I completely neglected to test anything with a null character in it. Aparently PHP completely ignores everything after a null character in the key name, but leaves it alone in the value.
Change the function fixStr to
return urldecode(str).replace(/([\"'])/g, '\\$1').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
Underneath
while(key.charAt(0) === ' ')
{
key = key.substr(1);
}add
if(key.indexOf('\0') !== -1)
{
key = key.substr(0, key.indexOf('\0'));
}
Looks good, stag019, thanks! Added in SVN. (Netbeans just caught the fact that "chr" needed to be declared too.). If you like, you might also consider voting for https://bugzilla.mozilla.org/show_bug.cgi?id=488227 as this is one behavior JS can't emulate from many PHP functions (in this case, we'd get a way to use parse_str() to put variables into a local scope only without using an array).
Oops, I also forgot to mention that the second parameter is now optional, as it uses the window variable if none is defined.
Sure, it parses strings such as array[key]=value into an array, in the same fashion PHP does. It also handles the encoding of the period and space characters, in the same fashion that PHP does.
stag019: Sorry but there are a lot function we need to maintain. Would it be possible for you to explain how your implementation beats our current one?
I couldn't think of a way to do it without eval(), but it better emulates PHP.
function parse_str(str, array)
{
var glue1 = '=', glue2 = '&', array2 = String(str).split(glue2),
i, j, tmp, key, value, bracket, keys, evalStr,
fixStr = function(str)
{
return urldecode(str).replace(/([\"'])/g, '\\$1').replace(/\0/g, '\\0').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
};
if(!array)
{
array = window;
}
for(i = 0; i < array2.length; i++)
{
tmp = array2[i].split(glue1);
if(tmp.length < 2)
{
tmp = [tmp, ''];
}
key = fixStr(tmp[0]);
value = fixStr(tmp[1]);
while(key.charAt(0) == ' ')
{
key = key.substr(1);
}
if(key && key.charAt(0) != '[')
{
keys = [];
bracket = 0;
for(j = 0; j < key.length; j++)
{
if(key.charAt(j) == '[' && !bracket)
{
bracket = j + 1;
}
else if(key.charAt(j) == ']')
{
if(bracket)
{
if(!keys.length)
{
keys.push(key.substr(0, bracket - 1));
}
keys.push(key.substr(bracket, j - bracket));
bracket = 0;
if(key.charAt(j + 1) !== '[')
{
break;
}
}
}
}
if(!keys.length)
{
keys = [key];
}
for(j = 0; j < keys[0].length; j++)
{
chr = keys[0].charAt(j);
if(chr == ' ' || chr == '.' || chr == '[')
{
keys[0] = keys[0].substr(0, j) + '_' + keys[0].substr(j + 1);
}
if(chr == '[')
{
break;
}
}
evalStr = 'array';
for(j = 0; j < keys.length; j++)
{
key = keys[j];
if((key !== '' && key !== ' ') || j === 0)
{
key = "'" + key + "'";
}
else
{
key = eval(evalStr + '.push([]);') - 1;
}
evalStr += '[' + key + ']';
if(j != keys.length - 1 && eval('typeof ' + evalStr) == 'undefined')
{
eval(evalStr + ' = [];');
}
}
evalStr += " = '" + value + "';\n";
eval(evalStr);
}
}
}
This function did not take into account the fact that the URL string might be encoded so I modified it to handle encoded URLs and added a new example.
[CODE="JavaScript"]
function parse_str(str, array){
// http://kevin.vanzonneveld.net
// + original by: Cagri Ekin
// * example 1: parse_str('first=foo&second=bar');
// * returns 1: { first: 'foo', second: 'bar' }
// * example 2: parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.');
// * returns 2: { str_a: "Jack and Jill didn't see the well." }
var glue1 = '=';
var glue2 = '&';
var array2 = str.split(glue2);
var array3 = [];
for(var x=0; x<array2.length; x++){
var tmp = array2[x].split(glue1);
array3[unescape(tmp[0])] = unescape(tmp[1]).replace(/[+]/g, ' '); // This is the modified line.
}
if(array){
array = array3;
} else {
return array3;
}
}
[/CODE]
http://crestidg.com


Brett Zamir
Aug 16th