Sé que se hicieron otras preguntas aquí, pero ninguna de ellas aborda este problema específico.
Cuando tenemos forma como:
<input name="A" .. /> <input name="B[x1]" .. /> <input name="C[y][z]".. />entonces todas las soluciones sugeridasaquí simplemente crean el JSON de jerarquía plana, como:
{ "A" : "1", "B[x1]" : "2" }Sin embargo, los datos de formulario correctos que debe crear deben ser:
{ "A" : "1", "B" : { "x1":"2 } }¿Hay algún enfoque JS estándar/incorporado para eso?
Usando Object.fromEntries para iterar sobre las entradas ;
Cada key de captura de bucle: value . si key no contiene [ agréguelo al objeto res , de lo contrario, obtenga los valores antiguos (objeto) de esa clave ei B y agréguelos al actual con su valor.
también podríamos usar Regex para obtener claves y valores anidados dinámicamente en lugar de indexOf
const obj = { A: "1", "B[x1]": "2", "B[x2]": "3", }; res = {}; Object.entries(obj).forEach((entry) => { const [key, value] = entry; if (!key.includes("[")) res[key] = value; else { const parentKey = key.slice(0, key.indexOf("[")); const childKey = key.slice(key.indexOf("[") + 1, -1); res[parentKey] = res[parentKey] ?? []; res[parentKey].push({ [childKey]: value }); } }); res; //? Result:
{ "A": "1", "B": [ { "x1": "2" }, { "x2": "3" } ] }Sorprendente, pero JS no tiene ninguna forma nativa/común de lograr este objetivo. La solución temporal (cuidado, esto no se ha probado exhaustivamente) que hice para mí necesita:
function formItemsToJson(FormElement){ let formDataEntries = new FormData(FormElement).entries(); const handleChild = function (obj,keysArr,value){ let firstK = keysArr.shift(); firstK=firstK.replace(']',''); if (keysArr.length==0){ if (firstK=='') { if (!Array.isArray(obj)) obj=[]; obj.push(value); } else obj[firstK] = value; } else{ if (firstK=='') obj.push(value); else { if ( ! ( firstK in obj) ) obj[firstK]={}; obj[firstK] = handleChild(obj[firstK],keysArr,value); } } return obj; }; let result = {}; for (const [key, value] of formDataEntries ) result= handleChild(result, key.split(/\[/), value); return result; } // USAGE : alert( JSON.stringify( formItemsToJson( document.querySelector('#myForm') ), null, 2 ) ); <form id="myForm"> <input type="hidden" name="A" value="11" /> <input type="hidden" name="C[E][m1]" value="22" /> <input type="hidden" name="C[E][m2]" value="23" /> <!-- only FormData can parse this below, because with JSON.stringify the below object will degrade,as same keys will be in conflict --> <input type="hidden" name="Y[Z][]" value="101" /> <input type="hidden" name="Y[Z][]" value="102" /> </form>