Ich weiß, dass dies ein alter Thread ist, aber vielleicht ist er noch relevant?
Inspiriert von Jacky Lis guter Lösung versuchte ich eine kleine Variation meiner eigenen mit dem Ziel, auch beliebige Kombinationen von Arrays und Objekten als Eingabe berücksichtigen zu können. Ich schaute mir an, wie PHP das gemacht hätte und versuchte, etwas "Ähnliches" in Gang zu bringen. Hier ist mein Code:
function getargs(str){
var ret={};
function build(urlnam,urlval,obj){ // extend the return object ...
var i,k,o=obj, x, rx=/\[([^\]]*)\]/g, idx=[urlnam.replace(rx,'')];
while (x=rx.exec(urlnam)) idx.push(x[1]);
while(true){
k=idx.shift();
if(k.trim()=='') {// key is empty: autoincremented index
if (o.constructor.name=='Array') k=o.length; // for Array
else if (o===obj ) {k=null} // for first level property name
else {k=-1; // for Object
for(i in o) if (+i>k) k=+i;
k++;
}
}
if(idx.length) {
// set up an array if the next key (idx[0]) appears to be
// numeric or empty, otherwise set up an object:
if (o[k]==null || typeof o[k]!='object') o[k]=isNaN(idx[0])?{}:[];
o=o[k]; // move on to the next level
}
else { // OK, time to store the urlval in its chosen place ...
// console.log('key',k,'val',urlval);
o[k]=urlval===""?null:urlval; break; // ... and leave the while loop.
}
}
return obj;
}
// ncnvt: is a flag that governs the conversion of
// numeric strings into numbers
var ncnvt=true,i,k,p,v,argarr=[],
ar=(str||window.location.search.substring(1)).split("&"),
l=ar.length;
for (i=0;i<l;i++) {if (ar[i]==="") continue;
p=ar[i].split("=");k=decodeURIComponent(p[0]);
v=p[1];v=(v!=null)?decodeURIComponent(v.replace(/\+/g,'%20')):'';
if (ncnvt && v.trim()>"" && !isNaN(v)) v-=0;
argarr.push([k,v]); // array: key-value-pairs of all arguments
}
for (i=0,l=argarr.length;i<l;i++) build(argarr[i][0],argarr[i][1],ret);
return ret;
}
Wenn die Funktion ohne das str-argument aufgerufen wird, wird sie window.location.search.slice(1)als Eingabe angenommen.
Einige Beispiele:
['a=1&a=2', // 1
'x[y][0][z][]=1', // 2
'hello=[%22world%22]&world=hello', // 3
'a=1&a=2&&b&c=3&d=&=e&', // 4
'fld[2][]=2&fld[][]=3&fld[3][]=4&fld[]=bb&fld[]=cc', // 5
$.param({a:[[1,2],[3,4],{aa:'one',bb:'two'},[5,6]]}), // 6
'a[]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13',// 7
'a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13'// 8
].map(function(v){return JSON.stringify(getargs(v));}).join('\n')
führt zu
{"a":2} // 1
{"x":{"y":[{"z":[1]}]}} // 2
{"hello":"[\"world\"]","world":"hello"} // 3
{"a":2,"b":null,"c":3,"d":null,"null":"e"} // 4 = { a: 2, b: null, c: 3, d: null, null: "e" }
{"fld":[null,null,[2],[3,4],"bb","cc"]} // 5
{"a":[[1,2],[3,4],{"aa":"one","bb":"two"},[5,6]]} // 6
{"a":["hi",2,null,[7,99],13]} // 7
{"a":{"0":2,"3":[7,99],"4":13,"x":"hi"}} // 8
Während Jacky Lis Lösung den Außenbehälter aals einfaches Objekt produzieren würde
{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output
getargs() Betrachtet den ersten angegebenen Index für eine beliebige Ebene, um festzustellen, ob diese Ebene ein Objekt (nicht numerischer Index) oder ein Array (numerisch oder leer) ist, was zu der Ausgabe führt, wie in der obigen Auflistung (Nr. 6) gezeigt.
Wenn das aktuelle Objekt ein Array ist null, wird es an jeder Stelle eingefügt, um leere Positionen darzustellen. Arrays sind immer fortlaufend nummeriert und 0-basiert.
Beachten Sie, dass im Beispiel Nr. 8 Die "automatische Inkrementierung" für leere Indizes funktioniert immer noch, obwohl es sich jetzt um ein Objekt und nicht um ein Array handelt.
Soweit ich es getestet habe, getargs()verhält sich mein Verhalten ziemlich identisch mit dem großartigen jQuery- $.deparam() Plugin von Chriss Roger, das in der akzeptierten Antwort erwähnt wird. Der wesentliche Unterschied besteht darin , dass getargsläuft ohne jQuery und dass es funktioniert Autoincrement in Objekte während $.deparam()wird nicht das tun:
JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);
führt zu
{"3":["7","99"],"x":"hi","undefined":"13"}
Im $.deparam()Index []wird undefinedanstelle eines automatisch inkrementierten numerischen Index interpretiert .
+. Jetzt ersetzt es alle!