如何将HTML5的FormData
对象中的条目转换为JSON格式?
解决方案不应使用jQuery。此外,它不应仅仅序列化整个FormData
对象,而是仅包含其键/值条目。
如何将HTML5的FormData
对象中的条目转换为JSON格式?
解决方案不应使用jQuery。此外,它不应仅仅序列化整个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);
对于那些想要支持多选列表或其他具有多个值的表单元素的人们(由于下面的答案有很多关于此问题的评论,我将添加一个可能的解决方案):
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);
这里有一个Fiddle演示了使用这种方法来处理简单的多选列表。
对于那些最终目的是将表单数据转换为 JSON 并通过XMLHttpRequest发送到服务器的人,你可以直接发送 FormData
对象,而不必进行转换。代码如下:
var request = new XMLHttpRequest();
request.open('POST', 'http://example.com/submitform.php');
request.send(formData);
参考MDN上的Using FormData Objects文档。
或者你也可以使用现代化的Fetch API来实现相同的功能:
fetch('http://example.com/submitform.php', {
method: 'POST',
body: formData
}).then((response) => {
// do something with response here...
});
请参阅MDN上的使用 Fetch API了解更多相关信息。
正如我在回答下面的评论中提到的,JSON中的stringify
方法并不支持所有类型的对象。关于支持哪些类型的信息,请参考MDN文档中的描述部分。
描述中还提到:
如果值具有toJSON()方法,则它负责定义将序列化哪些数据。
这意味着您可以提供自己的toJSON
序列化方法,并编写用于序列化自定义对象的逻辑。通过这种方式,您可以快速轻松地为更复杂的对象树构建序列化支持。
<SELECT MULTIPLE>
和<INPUT type="checkbox">
具有相同名称的多个值的答案,通过将值转换为数组来实现。 - somefetch
,请确保使用正确的标题与application/json
。 - Pro QJSON.stringify(Object.fromEntries(formData));
的答案会更好。 - Tom Stickel在2019年,这种任务变得非常容易。
JSON.stringify(Object.fromEntries(formData));
Object.fromEntries
:Chrome 73+、Firefox 63+和Safari 12.1以上版本支持。
如评论中所述,请注意:FormData
可以包含具有相同键的多个值(例如,名称相同的复选框)。Object.fromEntries()
会丢弃重复值并只保留最后一个值。
JSON.stringify(Object.fromEntries(formData.entries()));
。 - Kohver以下是一种更加函数式的方法,不需要使用任何库。
Array.from(formData.entries()).reduce((memo, [key, value]) => ({
...memo,
[key]: value,
}), {});
示例:
document.getElementById('foobar').addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Array.from(formData.entries()).reduce((memo, [key, value]) => ({
...memo,
[key]: value,
}), {});
document.getElementById('output').innerHTML = JSON.stringify(data);
});
<form id='foobar'>
<input name='baz' />
<input type='submit' />
</form>
<pre id='output'>Input some value and submit</pre>
[key, value]
替换pair
,以利用解构并提高可读性。 - Christian Vincenzo Traina到目前为止,我还没有看到有关FormData.getAll方法的任何提及。
除了从FormData对象中返回与给定密钥相关联的所有值之外,使用Object.fromEntries方法真的非常简单,正如其他人在这里指定的那样。
var formData = new FormData(document.forms[0])
var obj = Object.fromEntries(
Array.from(formData.keys()).map(key => [
key, formData.getAll(key).length > 1 ?
formData.getAll(key) : formData.get(key)
])
)
代码片段演示
var formData = new FormData(document.forms[0])
var obj = Object.fromEntries(Array.from(formData.keys()).map(key => [key, formData.getAll(key).length > 1 ? formData.getAll(key) : formData.get(key)]))
document.write(`<pre>${JSON.stringify(obj)}</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>
<SELECT multiple>
或具有相同名称的多个<INPUT type="checkbox">
,则需要注意并创建值数组。否则,您只会得到最后一个选择的值。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 的支持,因为它不支持在 FormData
上使用 ForEach
或 entries
)
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 );
}
如果你需要支持将嵌套字段序列化,类似于PHP处理表单字段的方式,你可以使用以下函数
function update(data, keys, value) {
if (keys.length === 0) {
// Leaf node
return value;
}
let key = keys.shift();
if (!key) {
data = data || [];
if (Array.isArray(data)) {
key = data.length;
}
}
// Try converting key to a numeric value
let index = +key;
if (!isNaN(index)) {
// We have a numeric index, make data a numeric array
// This will not work if this is a associative array
// with numeric keys
data = data || [];
key = index;
}
// If none of the above matched, we have an associative array
data = data || {};
let val = update(data[key], keys, value);
data[key] = val;
return data;
}
function serializeForm(form) {
return Array.from((new FormData(form)).entries())
.reduce((data, [field, value]) => {
let [_, prefix, keys] = field.match(/^([^\[]+)((?:\[[^\]]*\])*)/);
if (keys) {
keys = Array.from(keys.matchAll(/\[([^\]]*)\]/g), m => m[1]);
value = update(data[prefix], keys, value);
}
data[prefix] = value;
return data;
}, {});
}
document.getElementById('output').textContent = JSON.stringify(serializeForm(document.getElementById('form')), null, 2);
<form id="form">
<input name="field1" value="Field 1">
<input name="field2[]" value="Field 21">
<input name="field2[]" value="Field 22">
<input name="field3[a]" value="Field 3a">
<input name="field3[b]" value="Field 3b">
<input name="field3[c]" value="Field 3c">
<input name="field4[x][a]" value="Field xa">
<input name="field4[x][b]" value="Field xb">
<input name="field4[x][c]" value="Field xc">
<input name="field4[y][a]" value="Field ya">
<input name="field5[z][0]" value="Field z0">
<input name="field5[z][]" value="Field z1">
<input name="field6.z" value="Field 6Z0">
<input name="field6.z" value="Field 6Z1">
</form>
<h2>Output</h2>
<pre id="output">
</pre>
var myForm = document.getElementById('myForm');
myForm.addEventListener('submit', function(event)
{
event.preventDefault();
var formData = new FormData(myForm),
result = {};
for (var entry of formData.entries())
{
result[entry[0]] = entry[1];
}
result = JSON.stringify(result)
console.log(result);
});
for (const [key, value] of formData.entries())
- Teddy Zetterlund这篇文章已经有一年了...但是,我真的非常喜欢ES6 @dzuc的答案。然而,它并不能处理多个选择框或复选框。这已经被指出,并提供了代码解决方案。我发现它们很笨重,也不够优化。所以我写了两个版本基于@dzuc来处理这些情况:
let r=Array.from(fd).reduce(
(o , [k,v]) => (
(!o[k])
? {...o , [k] : v}
: {...o , [k] : [...o[k] , v]}
)
,{}
);
let obj=JSON.stringify(r);
Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
[]
后缀。let r=Array.from(fd).reduce(
(o , [k,v]) => (
(k.split('[').length>1)
? (k=k.split('[')[0]
, (!o[k])
? {...o , [k] : [v]}
: {...o , [k] : [...o[k] , v ]}
)
: {...o , [k] : v}
)
,{}
);
let obj=JSON.stringify(r);
一行热门版本:
Array.from(fd).reduce((o,[k,v])=>((k.split('[').length>1)?(k=k.split('[')[0],(!o[k])?{...o,[k]:[v]}:{...o,[k]:[...o[k],v]}):{...o,[k]:v}),{});
自上次编写上一个案例以来,在工作中遇到了具有多层复选框的 PHP 表单。我编写了一个新案例来支持先前的案例和这个案例。我创建了一个代码片段来更好地展示这个案例,结果显示在控制台上供演示使用,根据您的需求进行修改。尽我所能优化它而不影响性能,但是它会影响一些人的可读性。它利用了数组是对象且指向数组的变量保留为引用的特点。对于这个案例我并没有什么高招,随意修改。
let nosubmit = (e) => {
e.preventDefault();
const f = Array.from(new FormData(e.target));
const obj = f.reduce((o, [k, v]) => {
let a = v,
b, i,
m = k.split('['),
n = m[0],
l = m.length;
if (l > 1) {
a = b = o[n] || [];
for (i = 1; i < l; i++) {
m[i] = (m[i].split(']')[0] || b.length) * 1;
b = b[m[i]] = ((i + 1) == l) ? v : b[m[i]] || [];
}
}
return { ...o, [n]: a };
}, {});
console.log(obj);
}
document.querySelector('#theform').addEventListener('submit', nosubmit, {capture: true});
<h1>Multilevel Form</h1>
<form action="#" method="POST" enctype="multipart/form-data" id="theform">
<input type="hidden" name="_id" value="93242" />
<input type="hidden" name="_fid" value="45c0ec96929bc0d39a904ab5c7af70ef" />
<label>Select:
<select name="uselect">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
</label>
<br /><br />
<label>Checkboxes one level:<br/>
<input name="c1[]" type="checkbox" checked value="1"/>v1
<input name="c1[]" type="checkbox" checked value="2"/>v2
<input name="c1[]" type="checkbox" checked value="3"/>v3
</label>
<br /><br />
<label>Checkboxes two levels:<br/>
<input name="c2[0][]" type="checkbox" checked value="4"/>0 v4
<input name="c2[0][]" type="checkbox" checked value="5"/>0 v5
<input name="c2[0][]" type="checkbox" checked value="6"/>0 v6
<br/>
<input name="c2[1][]" type="checkbox" checked value="7"/>1 v7
<input name="c2[1][]" type="checkbox" checked value="8"/>1 v8
<input name="c2[1][]" type="checkbox" checked value="9"/>1 v9
</label>
<br /><br />
<label>Radios:
<input type="radio" name="uradio" value="yes">YES
<input type="radio" name="uradio" checked value="no">NO
</label>
<br /><br />
<input type="submit" value="Submit" />
</form>
Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {});
炫酷版 es2018 - nackjicholson易于使用的功能
我已经为此创建了一个功能函数
function FormDataToJSON(FormElement){
var formData = new FormData(FormElement);
var ConvertedJSON= {};
for (const [key, value] of formData.entries())
{
ConvertedJSON[key] = value;
}
return ConvertedJSON
}
使用示例
var ReceivedJSON = FormDataToJSON(document.getElementById('FormId'));
for
循环创建了一个空的JSON变量,在每次迭代中,我将formData对象中的key
作为JSON键。你可以在我的GitHub JS库中找到此代码,如果需要改进,请给我建议,我已经将代码放在这里:https://github.com/alijamal14/Utilities/blob/master/Utilities.js。<select multiple>
或<input type="checkbox">
的多个选定值。 - some例如,您可以拥有以下表单字段:
<select name="select[]" multiple></select>
<input name="check[a][0][]" type="checkbox" value="test"/>
使用方法:
let json = form2json(formData);
function form2json(data) {
let method = function (object,pair) {
let keys = pair[0].replace(/\]/g,'').split('[');
let key = keys[0];
let value = pair[1];
if (keys.length > 1) {
let i,x,segment;
let last = value;
let type = isNaN(keys[1]) ? {} : [];
value = segment = object[key] || type;
for (i = 1; i < keys.length; i++) {
x = keys[i];
if (i == keys.length-1) {
if (Array.isArray(segment)) {
segment.push(last);
} else {
segment[x] = last;
}
} else if (segment[x] == undefined) {
segment[x] = isNaN(keys[i+1]) ? {} : [];
}
segment = segment[x];
}
}
object[key] = value;
return object;
}
let object = Array.from(data).reduce(method,{});
return JSON.stringify(object);
}
JSON.stringify()
有帮助吗?也许你可以尝试其他方法来解决问题? - Justinaslet data = new URLSearchParams(formData)
。 - dlnsk