I know there were other questions asked here, but none of them addresses this specific issue.
When we have form like:
<input name="A" ..>
<input name="B[x1]" ..>
then all solutions suggested here just create the flat-hierarchy JSON, like:
{
"A" : "1",
"B[x1]" : "2"
}
However, the correct form-data it needs to be created should be :
{
"A" : "1",
"B" : {
"x1":"2
}
}
Is there any standard/builtin JS approach for that?
CodePudding user response:
Using Object.fromEntries
to iterate over entries;
Each loop grab key
: value
. if key
doesn't contain [
add it to object res
, else get old values(object) of that key e.i. B
and add them the current with its value.
we could use also use Regex
to grab nested key and values dynamically instead of 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"
}
]
}
CodePudding user response:
Surprising, but JS doesn't have any native/common way to achieve this goal. The temporary solution (beware, this is not extensively tested) I made for me needs:
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, and with JSON object this will be incorrecty parsed -->
<input type="hidden" name="Y[Z][]" value="101" />
<input type="hidden" name="Y[Z][]" value="102" />
</form>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>