Sé que este es un hilo viejo, pero ¿tal vez todavía tenga alguna relevancia?
Inspirado por la buena solución de Jacky Li, probé una ligera variación propia con el objetivo de ser capaz de manejar combinaciones arbitrarias de matrices y objetos como entrada. Miré cómo PHP lo habría hecho y traté de lograr algo "similar". Aquí está mi código:
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 se llama a la función sin el str
argumento-asumirá window.location.search.slice(1)
como entrada.
Algunos ejemplos:
['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')
resultados 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
Mientras que la solución de Jacky Li produciría el contenedor externo a
como un objeto simple
{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output
getargs()
mira el primer índice dado para cualquier nivel para determinar si este nivel será un objeto (índice no numérico) o una matriz (numérica o vacía), lo que da como resultado la salida como se muestra en el listado anterior (no. 6).
Si el objeto actual es una matriz, entonces null
s se inserta donde sea necesario para representar posiciones vacías. Las matrices siempre están numeradas consecutivamente y basadas en 0).
Tenga en cuenta que en el ejemplo no. 8 el "autoincremento" para índices vacíos todavía funciona, aunque ahora estemos tratando con un objeto y no con una matriz.
Hasta donde lo he probado, mi getargs()
comportamiento se comporta de manera casi idéntica al gran $.deparam()
complemento jQuery de Chriss Roger mencionado en la respuesta aceptada. La principal diferencia es que se getargs
ejecuta sin jQuery y que aumenta automáticamente en los objetos, mientras $.deparam()
que no lo hará:
JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);
resultados en
{"3":["7","99"],"x":"hi","undefined":"13"}
En $.deparam()
el índice []
se interpreta como un undefined
índice numérico autoincrementado en lugar de uno.
+
. ¡Ahora los reemplaza a todos!