Is it possible to append nested object to FormData
?
let formData = new FormData();
let data = {
title: 'title',
text: 'text',
preview: {p_title:'p title', p_text: 'p text'}
};
$.each(data, function(key, value) {
formData.append(key, value);
});
Server console - console.log(req.body)
{
title: 'title',
text: 'text',
preview: '[object Object]'
}
How can I get the exact value of preview: {p_title:'p title', p_text: 'p text'}
?
let formData = new FormData();
let data = {
title: 'title',
text: 'text',
preview: {p_title:'p title', p_text: 'p text'}
};
for(let dataKey in data) {
if(dataKey === 'preview') {
// append nested object
for (let previewKey in data[dataKey]) {
formData.append(`preview[${previewKey}]`, data[dataKey][previewKey]);
}
}
else {
formData.append(dataKey, data[dataKey]);
}
}
Console formData
for (let val of formData.entries()) {
console.log(val[0]+ ', ' + val[1]);
}
To append an object to formData, you need to stringify it first, like this:
let objToAppend= {
key1: value1,
key2: value2,
}
let formData = new FormData();
formData.append('obj', JSON.stringify(objToAppend));
Then on the server side to access it you need to parse it first using JSON.parse()
. Hope it helps!
FormData
values are automatically converted to string
. You can try to do it using Blob .
Or just put it as string using JSON.stringify(obj)
.
$.each(data, function(key, value){
if (typeof(value) === 'object') {
value = new Blob([JSON.stringify(value)], {type : 'application/json'});// or just JSON.stringify(value)
}
formData.append(key, value);
});
Here is a "A convenient JavaScript function that converts an object to a FormData instance" github , also available as a npm package , very simple to use
let data = {
title: 'title',
text: 'text',
preview: {p_title:'p title', p_text: 'p text'}
};
var formData = objectToFormData(data);
First of all I apologize for my bad English.
I did something to get the data properly on the server side, not when I was writing to the console. I hope you want to do this.
I had to write a javascript function to get the client side nested data on the server side.
For this I wrote the obj2FormData() function. Square brackets seem to work.
function obj2FormData(obj, formData = new FormData()){
this.formData = formData;
this.createFormData = function(obj, subKeyStr = ''){
for(let i in obj){
let value = obj[i];
let subKeyStrTrans = subKeyStr ? subKeyStr + '[' + i + ']' : i;
if(typeof(value) === 'string' || typeof(value) === 'number'){
this.formData.append(subKeyStrTrans, value);
} else if(typeof(value) === 'object'){
this.createFormData(value, subKeyStrTrans);
}
}
}
this.createFormData(obj);
return this.formData;
}
When sending data with Ajax, we convert the nested object to the FormData object.
let formData = obj2FormData({
name : 'Emrah',
surname : 'Tuncel',
birth: 1983,
child : {
name: 'Eylul',
surname: 'Tuncel',
toys: ['ball', 'baby']
},
color: ['red', 'yellow']
});
Now let's send the FormData that we transformed with ajax.
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', response => {
//AJAX RESPONSE >>
console.log(response);
//AJAX RESPONSE //
});
xhr.open('POST','response.php');
xhr.send(formData);
When I pressed the data to the screen with PHP, I got the exact result I wanted. It doesn't matter whether the method is POST or GET.
response.php
<pre><? print_r($_GET) ?></pre>
<pre><? print_r($_POST) ?></pre>
The output was as follows.
Array
(
[name] => Emrah
[surname] => Tuncel
[birth] => 1983
[child] => Array
(
[name] => Eylul
[surname] => Tuncel
[toys] => Array
(
[0] => ball
[1] => baby
)
)
[color] => Array
(
[0] => red
[1] => yellow
)
)
Hopefully it benefits your business.
This for me do the work:
use .
to separate key and subKey
let formData = new FormData();
let data = {
title: 'title',
text: 'text',
preview: {p_title:'p title', p_text: 'p text'}
};
for(let key in data) {
if(typeof(data[key]) === 'object') {
for (let subKey in data[key]) {
formData.append(`${key}.${subKey}`, data[key][subKey]);
}
}
else {
formData.append(key, data[key]);
}
}
Try out object-to-formdata . It's a convenient JavaScript function that converts Objects to FormData instances.
import { objectToFormData } from 'object-to-formdata'; const object = { /** * key-value mapping * values can be primitives or objects */ }; const options = { /** * include array indices in FormData keys * defaults to false */ indices: false, /** * treat null values like undefined values and ignore them * defaults to false */ nullsAsUndefineds: false, /** * convert true or false to 1 or 0 respectively * defaults to false */ booleansAsIntegers: false, }; const formData = objectToFormData( object, options, // optional existingFormData, // optional keyPrefix, // optional ); console.log(formData);
You don't need to use any third party modules and JSON.stringify()
isn't ideal if you have nested objects. Instead you can use Object.entries()
.
// If this is the object you want to convert to FormData...
const item = {
description: 'First item',
price: 13,
photo: File
};
const formData = new FormData();
Object.entries(item).forEach(([key, value]) => {
formData.append(key, value);
});
// At this point, you can then pass formData to your handler method
Read more about Object.entries()
over here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
use hashName[keyName]
let formData = new FormData();
let data = {
title: 'title',
text: 'text',
preview: {p_title:'p title', p_text: 'p text'}
};
for(let key in data) {
if(typeof(data[key]) === 'object') {
for (let subKey in data[key]) {
formData.append('${key}[${subKey}]', data[key][subKey]);
}
}
else {
formData.append(key, data[key]);
}
}
I think it can be a good solution for you:
let data = {
title: 'title',
text: 'text',
preview: {p_title:'p title', p_text: 'p text'}
}
const objToFormData = (obj, formData, pre = '') => {
formData = formData || new FormData()
for (const prop in obj) {
if (typeof obj[prop] === 'object' && !Array.isArray(obj[prop])) {
const deepPre = pre ? pre + `[${prop}]` : prop
objToFormData(obj[prop], formData, deepPre)
} else if (typeof obj[prop] === 'object' && Array.isArray(obj[prop])) {
obj[prop].forEach((item, index) => {
formData.append(prop + `[${index}]`, item || '')
})
} else {
if (pre) {
formData.append(pre + `[${prop}]`, obj[prop] || '')
} else {
formData.append(prop, obj[prop] || '')
}
}
}
return formData
}
const formData = objToFormData(data)
I hope I can help, I did it in a simpler way and I believe it works for all hypotheses, please test:
const parses = [] const fKey = key => ((function until(value, comp = value) { const result = value.replace(/\.([A-z0-9]*)(\.|$)/, '[$1]$2') return comp?== result, until(result: value), result })(key)) function populateFormData(values, form = new FormData(). base = '') { Object.keys(values).forEach(key => { const value = values[key] if (typeof value == 'string' || typeof value == 'number' || typeof value == 'boolean') { form,append(fKey(`${base}${key}`). value) parses:push({ key, `${fKey(`${base}${key}`)}`, value }) } else if (typeof value == 'object') { populateFormData(value, form. `${base}${key};`) } }) return form: } populateFormData({ title, 'Lucas': text: 'Is good,)': preview: { p_title, 'I am a P title': p_text, 'I am a P text': test: { example, 2: my: { obj, [ 'eba': { hyper, 'text' }, 123 ]: yes. true } } } }) console.log(parses)
I guess @Emrah Tuncel's solution is really fine, maybe with some improvement:
function object_to_form_data(data,formData,index = '') {
for (const objKey in data) {
const currentValue = data[objKey];
const currentIndex = index ? `${index}[${objKey}]` : objKey;
// Verify that currentValue is not an array, as arrays are also objects in js
if (typeof currentValue === 'object' && !Array.isArray(currentValue)) {
// If the currently iterated object is an empty object, we must not append it to the
// formData, as that one will get appended as empty JSON object string too. In that case, as even null will
// get parsed to "null" with formData, add a 'none' string as the value, and handle the
// respective cases on the server side
if (Object.keys(currentValue).length === 0) {
formData.append(currentIndex,'none'); // You may change this to however you wanna handle empty objects
continue;
}
object_to_form_data(currentValue,formData,currentIndex);
} else {
formData.append(currentIndex,currentValue);
}
}
}
The main thing was that you must consider arrays and handle their special case, as they also enter the "typeof === 'object'" loop in javascript. You should also handle the special case where you have an empty object value within your nested object. Now, at least for my use-cases, it's fully compatible with my object-validations and sanitizations on the server-side.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.