我怎样才能将我的JS对象转换为FormData?
我这样做的原因是,我有一个用~100个表单字段值构造的对象。
var item = {
description: 'Some Item',
price : '0.00',
srate : '0.00',
color : 'red',
...
...
}
现在我被要求将上传文件功能添加到我的表单,当然,通过JSON是不可能的,所以我计划移动到FormData。那么有什么方法可以将我的JS对象转换为FormData呢?
递归地
const toFormData = (f => f(f))(h => f => f(x => h(h)(f)(x)))(f => fd => pk => d => {
if (d instanceof Object) {
Object.keys(d).forEach(k => {
const v = d[k]
if (pk) k = `${pk}[${k}]`
if (v instanceof Object && !(v instanceof Date) && !(v instanceof File)) {
return f(fd)(k)(v)
} else {
fd.append(k, v)
}
})
}
return fd
})(new FormData())()
let data = {
name: 'John',
age: 30,
colors: ['red', 'green', 'blue'],
children: [
{ name: 'Max', age: 3 },
{ name: 'Madonna', age: 10 }
]
}
console.log('data', data)
document.getElementById("data").insertAdjacentHTML('beforeend', JSON.stringify(data))
let formData = toFormData(data)
for (let key of formData.keys()) {
console.log(key, formData.getAll(key).join(','))
document.getElementById("item").insertAdjacentHTML('beforeend', `<li>${key} = ${formData.getAll(key).join(',')}</li>`)
}
<p id="data"></p>
<ul id="item"></ul>
下面是一个使用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
阅读更多关于Object.entries()在这里- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
下面是一个非常简单的TypeScript实现,基于@Vladimir Novopashin和@developer033的回答。打印稿操场
type Serializeable =
| string
| number
| boolean
| null
| Date
| File
| { [x: string | number]: Serializeable }
| Array<Serializeable>;
function serialize(
data: Serializeable,
parentKey = '',
formData: FormData = new FormData()
): FormData {
if ( typeof data === 'string') {
formData.append(parentKey, data);
} else if ( typeof data === 'number') {
formData.append(parentKey, data.toString());
} else if ( typeof data === 'boolean') {
formData.append(parentKey, data ? 'true' : 'false');
} else if (data === null) {
formData.append(parentKey, 'null');
} else if (data instanceof Date) {
formData.append(parentKey, data.toISOString());
} else if (data instanceof File) {
formData.append(parentKey, data);
} else {
// Arrays and objects
Object.entries(data).forEach((entry: [string | number, Serializeable]) => {
const [key, value] = entry;
serialize(value, parentKey ? `${parentKey}[${key}]` : key.toString(), formData);
});
}
return formData;
}
使用ES6和更函数式的编程方法@adeneo的答案可能是这样的:
function getFormData(object) {
const formData = new FormData();
Object.keys(object).forEach(key => formData.append(key, object[key]));
return formData;
}
或者使用.reduce()和箭头函数:
const getFormData = object => Object.keys(object).reduce((formData, key) => {
formData.append(key, object[key]);
return formData;
}, new FormData());