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: 1109.2015 // 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(/^&?([\s\S]*?)&?$/, '$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.
using the function as described above, this string
"name=98_20&id_azienda=3&id_sede=12&revisione=0&selectFolder=linee&module_from=98_20&id_from=&id_orig=0&nome=Promemoria+pianificazione+prossimo+audit&descrizione=Promemoria+per+la+necessit%E0+di+pianificare+il+prossimo+audit&id_assegnatario=1&nome_assegnatario=SYSTEM"
causes a "malformed URI sequence" error.
How can we solve it? I do not see any error in the query string.
I was going to use this code then i saw the evals so i reimplemented it to this. Its faster, passes lint and its eval free :). I tested every make up of a query string i could think of and they all come out the same as the parse_str code above.
function parse_str_new (str, arr){
var strArr = (str+'').replace(/^&/, '').replace(/&$/, '').split('&'),
i,
tmp,
key,
value,
keyIndex,
subkey,
fixStr = function (str) {
return decodeURIComponent(str.replace(/\+/g, '%20'));
};
if (!arr) {
arr = this.window;
}
for (i = 0; i < strArr.length; i++) {
tmp = strArr[i].split("=");
key = fixStr(tmp[0]);
if(tmp.length < 2){
value = "";
}else{
value = fixStr(tmp[1]);
}
while (key.charAt(0) === ' ') {
key = key.substr(1);
}
if (key.indexOf("\x00") !== -1) {
key = key.substr(0, key.indexOf("\x00"));
}
if (key && key.charAt(0) !== '[') {
keyIndex = key.indexOf('[');
if(keyIndex !== -1&&key.indexOf(']',keyIndex) !== -1){
subkey = key.substring(keyIndex+1,key.indexOf(']',keyIndex));
key = key.substring(0,keyIndex).replace(/\.| /g,'_');
if(!arr[key]){
arr[key]=[];
}
if(subkey === ""){
arr[key].push(value);
}else{
arr[key][subkey]=value;
}
}else{
arr[key.replace(/\.| |\[/g,"_")] = value;
}
}
}
}
@e-mike. Thanks for the report. I had just assumed that was some cascading error that would be fixed by the fix I made, but now I've also addressed the urldecode issue you mention so the error should indeed now be avoided. (I'm just taking your word for it that PHP silently ignores missing, empty or null values, as I haven't confirmed in this case.) (I also just now simplified and expanded my earlier parse_str fix.)
The TypeError mentioned by Dreamer is still there (also in the git version).
The error is caused by urldecode (not parse_str). urldecode had a makeover not long ago and the error is since the makeover.
If the string (str) is empty, undefined or not a string you get this error.
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


David Pesta
Jan 2nd
Many of the array functions in the php.js library return javascript objects instead of javascript arrays, which is good. Javascript objects are much more PHPish than javascript arrays. But this function returns a javascript array instead of a javascript object, which can lead to unexpected problems if you are expecting this to behave like PHP (namely, a large number as a key will cause the javascript array to add null values in all of its indexes up to the value of that key, where in PHP it won't do that--pretty frustrating). To fix this, simply replace the [] with {} inside the eval on line 89 where the parent "arrays" are iteratively created. This will make it create objects instead.