Преобразование объекта JS в данные формы
как я могу преобразовать мой объект JS в FormData
?
причина, по которой я хочу это сделать, у меня есть объект, который я построил из ~100 значений поля формы.
var item = {
description: 'Some Item',
price : '0.00',
srate : '0.00',
color : 'red',
...
...
}
теперь меня просят добавить функцию загрузки файла в мою форму, которая, конечно, невозможна через JSON, и поэтому я планирую перейти к FormData
. Так есть ли способ, которым я могу преобразовать свой объект JS в FormData
?
8 ответов:
если у вас есть объект, вы можете легко создать объект FormData и добавить имена и значения из этого объекта в formData.
вы не опубликовали никакого кода, так что это общий пример;
var form_data = new FormData(); for ( var key in item ) { form_data.append(key, item[key]); } $.ajax({ url : 'http://example.com/upload.php', data : form_data, processData : false, contentType : false, type: 'POST' }).done(function(data){ // do stuff });
в документации по MDN
С ES6 и более функциональным подходом к программированию ответ @adeneo может выглядеть так:
function getFormData(object) { const formData = new FormData(); Object.keys(object).forEach(key => formData.append(key, object[key])); return formData; }
и с помощью
.reduce()
и со стрелками-функции:getFormData = object => Object.keys(object).reduce((formData, key) => { formData.append(key, object[key]); return formData; }, new FormData());
эта функция добавляет все данные из объекта в FormData
function appendFormdata(FormData, data, name){ name = name || ''; if (typeof data === 'object'){ $.each(data, function(index, value){ if (name == ''){ appendFormdata(FormData, value, index); } else { appendFormdata(FormData, value, name + '['+index+']'); } }) } else { FormData.append(name, data); } } var formData = new FormData(), your_object = { name: 'test object', another_object: { name: 'and other objects', value: 'whatever' } }; appendFormdata(formData, your_object);
у меня был сценарий, в котором вложенный JSON должен был быть сериализован линейным способом, пока данные формы строятся, так как именно так сервер ожидает значения. Итак, я написал небольшую рекурсивную функцию, которая переводит JSON, который выглядит так:
{ "orderPrice":"11", "cardNumber":"************1234", "id":"8796191359018", "accountHolderName":"Raj Pawan", "expiryMonth":"02", "expiryYear":"2019", "issueNumber":null, "billingAddress":{ "city":"Wonderland", "code":"8796682911767", "firstname":"Raj Pawan", "lastname":"Gumdal", "line1":"Addr Line 1", "line2":null, "state":"US-AS", "region":{ "isocode":"US-AS" }, "zip":"76767-6776" } }
в нечто вроде этого:
{ "orderPrice":"11", "cardNumber":"************1234", "id":"8796191359018", "accountHolderName":"Raj Pawan", "expiryMonth":"02", "expiryYear":"2019", "issueNumber":null, "billingAddress.city":"Wonderland", "billingAddress.code":"8796682911767", "billingAddress.firstname":"Raj Pawan", "billingAddress.lastname":"Gumdal", "billingAddress.line1":"Addr Line 1", "billingAddress.line2":null, "billingAddress.state":"US-AS", "billingAddress.region.isocode":"US-AS", "billingAddress.zip":"76767-6776" }
сервер будет принимать данные формы, которые находятся в этом преобразованном формате.
здесь функция:
function jsonToFormData (inJSON, inTestJSON, inFormData, parentKey) { // http://stackoverflow.com/a/22783314/260665 // Raj: Converts any nested JSON to formData. var form_data = inFormData || new FormData(); var testJSON = inTestJSON || {}; for ( var key in inJSON ) { // 1. If it is a recursion, then key has to be constructed like "parent.child" where parent JSON contains a child JSON // 2. Perform append data only if the value for key is not a JSON, recurse otherwise! var constructedKey = key; if (parentKey) { constructedKey = parentKey + "." + key; } var value = inJSON[key]; if (value && value.constructor === {}.constructor) { // This is a JSON, we now need to recurse! jsonToFormData (value, testJSON, form_data, constructedKey); } else { form_data.append(constructedKey, inJSON[key]); testJSON[constructedKey] = inJSON[key]; } } return form_data; }
ссылка:
var testJSON = {}; var form_data = jsonToFormData (jsonForPost, testJSON);
я использую testJSON только для просмотра преобразованных результатов, так как я не смогу извлечь содержимое form_data. Аякс пост назвать:
$.ajax({ type: "POST", url: somePostURL, data: form_data, processData : false, contentType : false, success: function (data) { }, error: function (e) { } });
другие ответы были неполными для меня. Я начал с ответа @Vladimir Novopashin и изменил его. Вот то, что мне нужно и ошибка, которую я нашел:
- поддержка файла
- поддержка массива
- ошибка: файл внутри сложного объекта должен быть добавлен с
.prop
вместо[prop]
. Например,formData.append('photos[0][file]', file)
не работал на google chrome, в то время какformData.append('photos[0].file', file)
работала- игнорировать некоторые свойства в моем объекте
в следующий код должен работать на IE11 и вечнозеленых браузерах.
function objectToFormData(obj, rootName, ignoreList) { var formData = new FormData(); function appendFormData(data, root) { if (!ignore(root)) { root = root || ''; if (data instanceof File) { formData.append(root, data); } else if (Array.isArray(data)) { for (var i = 0; i < data.length; i++) { appendFormData(data[i], root + '[' + i + ']'); } } else if (typeof data === 'object' && data) { for (var key in data) { if (data.hasOwnProperty(key)) { if (root === '') { appendFormData(data[key], key); } else { appendFormData(data[key], root + '.' + key); } } } } else { if (data !== null && typeof data !== 'undefined') { formData.append(root, data); } } } } function ignore(root){ return Array.isArray(ignoreList) && ignoreList.some(function(x) { return x === root; }); } appendFormData(obj, rootName); return formData; }
извините за поздний ответ, но я боролся с этим, как угловой 2 в настоящее время не поддерживает загрузку файлов. Итак, способ сделать это был отправка
XMLHttpRequest
СFormData
. Итак, я создал функцию, чтобы сделать это. Я использую Typescript. Чтобы преобразовать его в Javascript просто удалите объявление типов данных./** * Transforms the json data into form data. * * Example: * * Input: * * fd = new FormData(); * dob = { * name: 'phone', * photos: ['myphoto.jpg', 'myotherphoto.png'], * price: '615.99', * color: { * front: 'red', * back: 'blue' * }, * buttons: ['power', 'volup', 'voldown'], * cameras: [{ * name: 'front', * res: '5Mpx' * },{ * name: 'back', * res: '10Mpx' * }] * }; * Say we want to replace 'myotherphoto.png'. We'll have this 'fob'. * fob = { * photos: [null, <File object>] * }; * Say we want to wrap the object (Rails way): * p = 'product'; * * Output: * * 'fd' object updated. Now it will have these key-values "<key>, <value>": * * product[name], phone * product[photos][], myphoto.jpg * product[photos][], <File object> * product[color][front], red * product[color][back], blue * product[buttons][], power * product[buttons][], volup * product[buttons][], voldown * product[cameras][][name], front * product[cameras][][res], 5Mpx * product[cameras][][name], back * product[cameras][][res], 10Mpx * * @param {FormData} fd FormData object where items will be appended to. * @param {Object} dob Data object where items will be read from. * @param {Object = null} fob File object where items will override dob's. * @param {string = ''} p Prefix. Useful for wrapping objects and necessary for internal use (as this is a recursive method). */ append(fd: FormData, dob: Object, fob: Object = null, p: string = ''){ let apnd = this.append; function isObj(dob, fob, p){ if(typeof dob == "object"){ if(!!dob && dob.constructor === Array){ p += '[]'; for(let i = 0; i < dob.length; i++){ let aux_fob = !!fob ? fob[i] : fob; isObj(dob[i], aux_fob, p); } } else { apnd(fd, dob, fob, p); } } else { let value = !!fob ? fob : dob; fd.append(p, value); } } for(let prop in dob){ let aux_p = p == '' ? prop : `${p}[${prop}]`; let aux_fob = !!fob ? fob[prop] : fob; isObj(dob[prop], aux_fob, aux_p); } }
версия TypeScript:
static convertModelToFormData(model: any, form: FormData = null, namespace = ''): FormData { let formData = form || new FormData(); for (let propertyName in model) { if (!model.hasOwnProperty(propertyName) || model[propertyName] == undefined) continue; let formKey = namespace ? `${namespace}[${propertyName}]` : propertyName; if (model[propertyName] instanceof Date) { formData.append(formKey, this.dateTimeToString(model[propertyName])); } else if (model[propertyName] instanceof Array) { model[propertyName].forEach((element, index) => { if (typeof element != 'object') formData.append(`${formKey}[]`, element); else { const tempFormKey = `${formKey}[${index}]`; this.convertModelToFormData(element, formData, tempFormKey); } }); } else if (typeof model[propertyName] === 'object' && !(model[propertyName] instanceof File)) { this.convertModelToFormData(model[propertyName], formData, formKey); } else { formData.append(formKey, model[propertyName].toString()); } } return formData; }
https://gist.github.com/Mds92/091828ea857cc556db2ca0f991fee9f6
попробуйте obj2fd =>https://www.npmjs.com/package/obj2fd
import obj2fd from 'obj2fd' let data = {a:1, b:2, c:{ca:1}}; let dataWithFormData = obj2fd(data); //result => [a=>1, b=>2, c=>[ca=>1]]
Comments