Je sais que c'est un vieux fil, mais peut-être qu'il y a encore une certaine pertinence?
Inspiré par la bonne solution de Jacky Li, j'ai essayé une légère variation de ma part avec l'objectif de pouvoir également prendre en charge des combinaisons arbitraires de tableaux et d'objets en entrée. J'ai regardé comment PHP l'aurait fait et j'ai essayé d'obtenir quelque chose de "similaire". Voici mon 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;
}
Si la fonction est appelée sans l' str
argument, elle sera considérée window.location.search.slice(1)
comme une entrée.
Quelques exemples:
['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')
résulte en
{"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
Alors que la solution de Jacky Li produirait le conteneur extérieur a
comme un objet simple
{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output
getargs()
regarde le premier index donné pour n'importe quel niveau pour déterminer si ce niveau sera un objet (index non numérique) ou un tableau (numérique ou vide), résultant ainsi en la sortie comme indiqué dans la liste ci-dessus (n ° 6).
Si l'objet courant est un tableau, les null
s sont insérés là où c'est nécessaire pour représenter des positions vides. Les tableaux sont toujours numérotés et basés sur 0).
Notez que dans l'exemple no. 8 "l'auto-incrémentation" pour les index vides fonctionne toujours, même si nous avons affaire à un objet maintenant et non à un tableau.
Pour autant que je l'ai testé, mon getargs()
comportement est à peu près identique au grand $.deparam()
plugin jQuery de Chriss Roger mentionné dans la réponse acceptée. La principale différence est que getargs
s'exécute sans jQuery et qu'il effectue l' auto - incrémentation dans les objets alors $.deparam()
qu'il ne le fera pas :
JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);
résulte en
{"3":["7","99"],"x":"hi","undefined":"13"}
Dans $.deparam()
l'index []
est interprété comme un undefined
index numérique auto-incrémenté au lieu d'un index.
+
. Maintenant, il les remplace tous!