I've been trying to get a nested object from formData from a form with nested keys like the below:
<input name="item[0][id]" value="0121"/>
<input name="item[0][name]" value="Birmingham"/>
<input name="item[1][id]" value="01675"/>
<input name="item[1][name]" value="Warwickshire"/>
To be formatted as an object like this:
{
'item': [
{
'id': '0121',
'name': 'Birmingham'
},
{
'id': '01675',
'name': 'Warwickshire'
}
]
}
Not:
{
'item[0][id]': '0121',
'item[0][name]': 'Birmingham',
'item[1][id]': '01675',
'item[1][name]': 'Warwickshire'
}
Currently I'm using the below, which is outputting in the format above.
const formData = new FormData(this.form);
const object = Object.fromEntries(formData);
Essentially, I'd like to have the form data formatted as it would be when it gets received by PHP for example.
You could use something like lodash's _.set
function, or else an implementation of the same feature in vanilla JavaScript, which I will use in below snippet:
// This function is taken from https://stackoverflow.com/a/54733755/5459839
function deepSet(obj, path, value) {
if (Object(obj) !== obj) return obj; // When obj is not an object
// If not yet an array, get the keys from the string-path
if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
path.slice(0,-1).reduce((a, c, i) => // Iterate all of them except the last one
Object(a[c]) === a[c] // Does the key exist and is its value an object?
// Yes: then follow that path
? a[c]
// No: create the key. Is the next key a potential array-index?
: a[c] = Math.abs(path[i+1])>>0 === +path[i+1]
? [] // Yes: assign a new array object
: {}, // No: assign a new plain object
obj)[path[path.length-1]] = value; // Finally assign the value to the last key
return obj; // Return the top-level object to allow chaining
}
// Use it for formData:
function formDataObject(form) {
const formData = new FormData(form);
const root = {};
for (const [path, value] of formData) {
deepSet(root, path, value);
}
return root;
}
// Example run
const result = formDataObject(document.forms[0]);
console.log(result);
<form>
<input name="item[0][id]" value="0121"/>
<input name="item[0][name]" value="Birmingham"/>
<input name="item[1][id]" value="01675"/>
<input name="item[1][name]" value="Warwickshire"/>
</form>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With