我如何将条目从HTML5 FormData对象转换为JSON?
解决方案不应该使用jQuery。而且,它不应该简单地序列化整个FormData对象,而应该只序列化它的键/值条目。
我如何将条目从HTML5 FormData对象转换为JSON?
解决方案不应该使用jQuery。而且,它不应该简单地序列化整个FormData对象,而应该只序列化它的键/值条目。
当前回答
这解决了我的问题,这是一个对象
const formDataObject = (formData) => {
for (const key in formData) {
if (formData[key].startsWith('{') || formData[key].startsWith('[')) {
try {
formData[key] = JSON.parse(formData[key]);
console.log("key is :", key, "form data is :", formData[key]);
} catch (error) {
console.log("error :", key);
}
}
}
console.log("object", formData)
}
其他回答
你也可以直接在FormData对象上使用forEach:
var object = {};
formData.forEach(function(value, key){
object[key] = value;
});
var json = JSON.stringify(object);
更新:
对于那些喜欢使用ES6箭头函数的相同解决方案的人:
var object = {};
formData.forEach((value, key) => object[key] = value);
var json = JSON.stringify(object);
更新2:
对于那些想要支持多选择列表或其他具有多个值的表单元素的人(因为关于这个问题的答案下面有很多评论,我将添加一个可能的解决方案):
var object = {};
formData.forEach((value, key) => {
// Reflect.has in favor of: object.hasOwnProperty(key)
if(!Reflect.has(object, key)){
object[key] = value;
return;
}
if(!Array.isArray(object[key])){
object[key] = [object[key]];
}
object[key].push(value);
});
var json = JSON.stringify(object);
这里用一个简单的多选择列表演示了这种方法的使用。
更新3:
这里要补充一点,如果将表单数据转换为json的目的是通过XML HTTP请求将其发送到服务器,则可以直接发送FormData对象而无需转换它。就这么简单:
var request = new XMLHttpRequest();
request.open("POST", "http://example.com/submitform.php");
request.send(formData);
参考MDN上使用FormData对象:
更新4:
正如下面我回答的一个评论中提到的,JSON stringify方法不会对所有类型的对象开箱即用。关于支持的类型的更多信息,我想参考JSON.stringify MDN文档中的描述部分。
在描述中还提到:
如果值具有toJSON()方法,则它负责定义将序列化的数据。
这意味着您可以提供自己的toJSON序列化方法,其中包含序列化自定义对象的逻辑。这样,您就可以快速轻松地为更复杂的对象树构建序列化支持。
下面是一种包含处理多个值的简单方法的方法。如果一个键以[]结尾,它将值组合成一个数组(就像在旧的php约定中一样),并从键中删除[]:
function formDataToJson(f) {
return Object.fromEntries(Array.from(f.keys(), k =>
k.endsWith('[]') ? [k.slice(0, -2), f.getAll(k)] : [k, f.get(k)]));
}
例如,如果你有:
const f = new FormData();
f.append("a", "1");
f.append("a", "2");
f.append("b[]", "3");
f.append("b[]", "4");
formDataToJson(f) // --> produces {a: "1", b: ["3","4"]}
我在这里迟到了。但是,我做了一个简单的方法来检查输入type="checkbox"
var formData = new FormData($form.get(0));
var objectData = {};
formData.forEach(function (value, key) {
var updatedValue = value;
if ($('input[name="' + key + '"]').attr("type") === "checkbox" && $('input[name="' + key + '"]').is(":checked")) {
updatedValue = true; // we don't set false due to it is by default on HTML
}
objectData[key] = updatedValue;
});
var jsonData = JSON.stringify(objectData);
我希望这能帮助到其他人。
如果你有多个相同名称的条目,例如如果你使用<SELECT multiple>或有多个<INPUT type="checkbox">具有相同的名称,你需要注意这一点,并将值创建一个数组。否则只能得到最后选中的值。
以下是es6的现代版本:
function formToJSON( elem ) {
let output = {};
new FormData( elem ).forEach(
( value, key ) => {
// Check if property already exist
if ( Object.prototype.hasOwnProperty.call( output, key ) ) {
let current = output[ key ];
if ( !Array.isArray( current ) ) {
// If it's not an array, convert it to an array.
current = output[ key ] = [ current ];
}
current.push( value ); // Add the new value to the array.
} else {
output[ key ] = value;
}
}
);
return JSON.stringify( output );
}
稍旧的代码(但IE11仍然不支持,因为它不支持ForEach或FormData上的条目)
function formToJSON( elem ) {
var current, entries, item, key, output, value;
output = {};
entries = new FormData( elem ).entries();
// Iterate over values, and assign to item.
while ( item = entries.next().value )
{
// assign to variables to make the code more readable.
key = item[0];
value = item[1];
// Check if key already exist
if (Object.prototype.hasOwnProperty.call( output, key)) {
current = output[ key ];
if ( !Array.isArray( current ) ) {
// If it's not an array, convert it to an array.
current = output[ key ] = [ current ];
}
current.push( value ); // Add the new value to the array.
} else {
output[ key ] = value;
}
}
return JSON.stringify( output );
}
使用JSON.stringify()中描述的toJSON
如果值具有toJSON()方法,则它负责定义将序列化的数据。
这里有一个小技巧。
var fd = new FormData(document.forms[0]); fd.toJSON = function() { const o = {}; this.forEach((v, k) => { v = this.getAll(k); o[k] = v.length == 1 ? v[0] : (v.length >= 1 ? v : null); }); return o; }; document.write(`<pre>${JSON.stringify(fd)}</pre>`) <form action="#"> <input name="name" value="Robinson" /> <input name="items" value="Vin" /> <input name="items" value="Fromage" /> <select name="animals" multiple id="animals"> <option value="tiger" selected>Tigre</option> <option value="turtle" selected>Tortue</option> <option value="monkey">Singe</option> </select> </form>