Làm cách nào để chuyển đổi đối tượng HTML5 FormData sang JSON? Nếu không có Jquery và xử lý các thuộc tính lồng nhau trong FormData như một đối tượng.
Làm cách nào để chuyển đổi đối tượng HTML5 FormData sang JSON? Nếu không có Jquery và xử lý các thuộc tính lồng nhau trong FormData như một đối tượng.
Câu trả lời:
Bạn cũng có thể sử dụng trực tiếp forEach
trên FormData
đối tượng:
var object = {};
formData.forEach(function(value, key){
object[key] = value;
});
var json = JSON.stringify(object);
Và đối với những người thích giải pháp tương tự với các chức năng mũi tên của ES6 :
var object = {};
formData.forEach((value, key) => {object[key] = value});
var json = JSON.stringify(object);
Và đối với những người muốn hỗ trợ cho danh sách nhiều lựa chọn hoặc các phần tử biểu mẫu khác có nhiều giá trị (vì có rất nhiều nhận xét bên dưới câu trả lời liên quan đến vấn đề này, tôi sẽ thêm một giải pháp khả thi) :
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);
Đây là một Fiddle trình bày việc sử dụng phương pháp này với một danh sách nhiều lựa chọn đơn giản.
Một lưu ý nhỏ cho những người kết thúc ở đây, trong trường hợp mục đích của việc chuyển đổi dữ liệu biểu mẫu sang json là để gửi nó thông qua một yêu cầu HTTP XML đến một máy chủ, bạn có thể gửi FormData
đối tượng trực tiếp mà không cần chuyển đổi nó. Đơn giản như sau:
var request = new XMLHttpRequest();
request.open("POST", "http://example.com/submitform.php");
request.send(formData);
Xem cũng dùng FormData Objects trên MDN để tham khảo :
Như đã đề cập trong một trong những nhận xét bên dưới câu trả lời của tôi, stringify
phương thức JSON sẽ không hoạt động tốt cho tất cả các loại đối tượng. Để biết thêm thông tin về những loại nào được hỗ trợ, tôi muốn tham khảo phần Mô tả trong tài liệu MDN củaJSON.stringify
.
Trong mô tả cũng đề cập rằng:
Nếu giá trị có phương thức toJSON (), nó có trách nhiệm xác định dữ liệu nào sẽ được tuần tự hóa.
Điều này có nghĩa là bạn có thể cung cấp toJSON
phương pháp tuần tự hóa của riêng mình với logic để tuần tự hóa các đối tượng tùy chỉnh của bạn. Như vậy, bạn có thể nhanh chóng và dễ dàng xây dựng hỗ trợ tuần tự hóa cho các cây đối tượng phức tạp hơn.
<SELECT MULTIPLE>
và <INPUT type="checkbox">
cùng tên, bằng cách chuyển đổi giá trị thành một mảng.
JSON.stringify(Object.fromEntries(formData));
rất nhiều đẹp hơn
Vào năm 2019, loại nhiệm vụ này trở nên siêu dễ dàng.
JSON.stringify(Object.fromEntries(formData));
Object.fromEntries
: Được hỗ trợ trong Chrome 73+, Firefox 63+, Safari 12.1
<select multiple>
hoặc <input type="checkbox">
😞
JSON.stringify(Object.fromEntries(formData.entries()));
Đây là một cách để làm điều đó theo phong cách chức năng hơn mà không cần sử dụng thư viện.
Array.from(formData.entries()).reduce((memo, pair) => ({
...memo,
[pair[0]]: pair[1],
}), {});
Thí dụ:
document.getElementById('foobar').addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Array.from(formData.entries()).reduce((memo, pair) => ({
...memo,
[pair[0]]: pair[1],
}), {});
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>
Nếu bạn có nhiều mục nhập có cùng tên, chẳng hạn như nếu bạn sử dụng <SELECT multiple>
hoặc có nhiều mục nhập <INPUT type="checkbox">
có cùng tên, bạn cần quan tâm đến điều đó và tạo một mảng giá trị. Nếu không, bạn chỉ nhận được giá trị được chọn cuối cùng.
Đây là biến thể ES6 hiện đại:
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 );
}
Mã cũ hơn một chút (nhưng vẫn không được IE11 hỗ trợ, vì nó không hỗ trợ ForEach
hoặc entries
bật 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 );
}
Bạn có thể đạt được điều này bằng cách sử dụng đối tượng FormData () . Đối tượng FormData này sẽ được điền các khóa / giá trị hiện tại của biểu mẫu bằng cách sử dụng thuộc tính tên của từng phần tử cho các khóa và giá trị đã gửi của chúng cho các giá trị. Nó cũng sẽ mã hóa nội dung đầu vào của tệp.
Thí dụ:
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())
Chức năng dễ sử dụng
Tôi đã tạo một chức năng cho việc này
function FormDataToJSON(FormElement){
var formData = new FormData(FormElement);
var ConvertedJSON= {};
for (const [key, value] of formData.entries())
{
ConvertedJSON[key] = value;
}
return ConvertedJSON
}
Ví dụ sử dụng
var ReceivedJSON = FormDataToJSON(document.getElementById('FormId');)
Trong đoạn mã này, tôi đã tạo biến JSON trống bằng cách sử dụng for
vòng lặp Tôi đã sử dụng key
s từ Đối tượng formData đến Khóa JSON trong mỗi Itration.
Bạn Tìm Mã Này Trong Thư Viện JS của Tôi Trên GitHub Hãy Đề Xuất Cho Tôi Nếu Nó Cần Cải Tiến Tôi Đã Đặt Mã Ở Đây https://github.com/alijamal14/Utilities/blob/master/Utilities.js
<select multiple>
hoặc <input type="checkbox">
.
Bài đăng này đã được một năm ... nhưng tôi thực sự rất thích câu trả lời của ES6 @dzuc. Tuy nhiên, nó không đầy đủ bởi không thể xử lý nhiều hộp chọn hoặc hộp kiểm. Điều này đã được chỉ ra và các giải pháp mã đã được cung cấp. Tôi thấy chúng nặng và không được tối ưu hóa. Vì vậy, tôi đã viết 2 phiên bản dựa trên @dzuc để xử lý các trường hợp này:
let r=Array.from(fd).reduce(
(o , [k,v]) => (
(!o[k])
? {...o , [k] : v}
: {...o , [k] : [...o[k] , v]}
)
,{}
);
let obj=JSON.stringify(r);
Phiên bản Hotshot một dòng:
Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
[]
hậu tố.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);
Phiên bản Hotshot một dòng:
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}),{});
Kể từ lần trước tôi đã viết trường hợp thứ hai trước đó, đã xảy ra trường hợp biểu mẫu PHP có hộp kiểm trên nhiều cấp. Tôi đã viết một trường hợp mới để hỗ trợ trường hợp trước và trường hợp này. Tôi đã tạo một đoạn mã để giới thiệu tốt hơn trường hợp này, kết quả hiển thị trên bảng điều khiển cho bản trình diễn này, hãy sửa đổi điều này theo nhu cầu của bạn. Đã cố gắng tối ưu hóa nó tốt nhất tôi có thể mà không ảnh hưởng đến hiệu suất, tuy nhiên, nó ảnh hưởng đến khả năng đọc của một số người. Lợi ích của mảng là các đối tượng và các biến trỏ đến mảng được giữ dưới dạng tham chiếu. Không hotshot cho cái này, hãy là khách của tôi.
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}), {});
hotshot phiên bản es2018
Phương thức FormData .entries
và for of
biểu thức không được hỗ trợ trong IE11 và Safari.
Đây là phiên bản đơn giản hơn để hỗ trợ Safari, Chrome, Firefox và Edge
function formDataToJSON(formElement) {
var formData = new FormData(formElement),
convertedJSON = {};
formData.forEach(function(value, key) {
convertedJSON[key] = value;
});
return convertedJSON;
}
Cảnh báo: câu trả lời này không hoạt động trong IE11.
FormData không có forEach
phương thức trong IE11.
Tôi vẫn đang tìm kiếm giải pháp cuối cùng để hỗ trợ tất cả các trình duyệt chính.
Nếu bạn đang sử dụng lodash, nó có thể được thực hiện ngắn gọn với fromPairs
import {fromPairs} from 'lodash';
const object = fromPairs(Array.from(formData.entries()));
Nếu bạn cần hỗ trợ để tuần tự hóa các trường lồng nhau, tương tự như cách PHP xử lý các trường biểu mẫu, bạn có thể sử dụng hàm sau
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>
Bạn có thể thử cái này
formDataToJSON($('#form_example'));
# Create a function to convert the serialize and convert the form data
# to JSON
# @param : $('#form_example');
# @return a JSON Stringify
function formDataToJSON(form) {
let obj = {};
let formData = form.serialize();
let formArray = formData.split("&");
for (inputData of formArray){
let dataTmp = inputData.split('=');
obj[dataTmp[0]] = dataTmp[1];
}
return JSON.stringify(obj);
}
Mặc dù câu trả lời từ @dzuc đã rất hay, bạn có thể sử dụng cấu trúc mảng (có sẵn trong các trình duyệt hiện đại hoặc với Babel) để làm cho nó thanh lịch hơn một chút:
// original version from @dzuc
const data = Array.from(formData.entries())
.reduce((memo, pair) => ({
...memo,
[pair[0]: pair[1],
}), {})
// with array destructuring
const data = Array.from(formData.entries())
.reduce((memo,[key, value]) => ({
...memo,
[key]: value,
}), {})
Lạm dụng một lớp lót!
Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {});
Hôm nay tôi học được firefox có hỗ trợ lây lan đối tượng và cấu trúc mảng!
Nếu các mặt hàng sau đáp ứng nhu cầu của bạn, bạn đang gặp may:
[['key','value1'], ['key2','value2']
(như những gì FormData cung cấp cho bạn) thành một đối tượng key-> value như thế nào {key1: 'value1', key2: 'value2'}
và chuyển đổi nó thành một chuỗi JSON.Đây là mã bạn sẽ cần:
const data = new FormData(document.querySelector('form'));
const json = JSON.stringify(Array.from(data).reduce((o,[k,v])=>(o[k]=v,o),{}));
Hy vọng điều này sẽ giúp ai đó.
Tôi chưa thấy đề cập nào về phương thức FormData.getAll cho đến nay.
Bên cạnh việc trả về tất cả các giá trị được liên kết với một khóa nhất định từ bên trong một đối tượng FormData, nó thực sự đơn giản bằng cách sử dụng phương thức Object.fromEntries như được chỉ định bởi những người khác ở đây.
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)
])
)
Đoạn mã đang hoạt động
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>
Đã làm cho tôi
var myForm = document.getElementById("form");
var formData = new FormData(myForm),
obj = {};
for (var entry of formData.entries()){
obj[entry[0]] = entry[1];
}
console.log(obj);
<select multiple>
hoặc<input type="checkbox">
Trong biểu mẫu trường hợp của tôi Dữ liệu là dữ liệu, cơ sở cháy đã mong đợi một đối tượng nhưng dữ liệu chứa đối tượng cũng như tất cả các nội dung khác nên tôi đã thử data.value nó hoạt động !!!
Tôi đến đây muộn. Tuy nhiên, tôi đã thực hiện một phương pháp đơn giản để kiểm tra loại đầu vào = "hộp kiểm"
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);
Tôi hy vọng điều này sẽ giúp ai đó khác.
Bạn có thể thực hiện công việc này một cách dễ dàng mà không cần sử dụng bất cứ thứ gì đặc biệt. Một mã như dưới đây là đủ.
var form = $(e.currentTarget);
var formData = objectifyForm(form);
function objectifyForm(formArray) {
var returnArray = {};
for (var i = 0; i < formArray[0].length; i++) {
var name = formArray[0][i]['name'];
if (name == "") continue;
if (formArray[0][i]['type'] == "hidden" && returnArray[name] != undefined) continue;
if ($(formArray[0][i]).attr("type") == "radio") {
var radioInputs = $("[name='" + name + "']");
var value = null;
radioInputs.each(function (radio) {
if ($(this)[0].checked == true) {
value = $(this).attr("id").split("_")[$(this).attr("id").split("_").length - 1];
}
});
returnArray[name] = value;
}
else if ($(formArray[0][i]).attr("type") == "checkbox") {
returnArray[name] = $(formArray[0][i])[0].checked;
}
else
returnArray[name] = formArray[0][i]['value'];
}
return returnArray;
};
JSON.stringify()
giúp không? Có thể bạn cố gắng sửa chữa một cái gì đó có thể được thực hiện theo cách khác?