Bagaimana cara mengonversi objek HTML5 FormData ke JSON? Tanpa Jquery dan menangani properti bersarang di FormData seperti objek.
Bagaimana cara mengonversi objek HTML5 FormData ke JSON? Tanpa Jquery dan menangani properti bersarang di FormData seperti objek.
Jawaban:
Anda juga bisa menggunakan forEach
pada FormData
objek langsung:
var object = {};
formData.forEach(function(value, key){
object[key] = value;
});
var json = JSON.stringify(object);
Dan bagi mereka yang lebih memilih solusi yang sama dengan fungsi panah ES6 :
var object = {};
formData.forEach((value, key) => object[key] = value);
var json = JSON.stringify(object);
Dan bagi mereka yang menginginkan dukungan untuk daftar pilihan ganda atau elemen formulir lainnya dengan banyak nilai (karena ada begitu banyak komentar di bawah jawaban mengenai masalah ini, saya akan menambahkan solusi yang mungkin) :
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);
Di sini Fiddle mendemonstrasikan penggunaan metode ini dengan daftar pilih multi sederhana.
Sebagai catatan tambahan bagi mereka yang berakhir di sini, jika tujuan mengonversi data formulir ke json adalah mengirimnya melalui permintaan HTTP XML ke server, Anda dapat mengirim FormData
objek secara langsung tanpa mengubahnya. Sesederhana ini:
var request = new XMLHttpRequest();
request.open("POST", "http://example.com/submitform.php");
request.send(formData);
Lihat juga Menggunakan Objek FormData di MDN untuk referensi :
Seperti disebutkan dalam salah satu komentar di bawah jawaban saya, stringify
metode JSON tidak akan berfungsi di luar kotak untuk semua jenis objek. Untuk informasi lebih lanjut tentang jenis apa yang didukung, saya ingin merujuk ke bagian Deskripsi di dokumentasi MDNJSON.stringify
.
Dalam uraian tersebut juga disebutkan bahwa:
Jika nilai memiliki metode toJSON (), itu bertanggung jawab untuk menentukan data apa yang akan diserialkan.
Ini berarti Anda dapat menyediakan toJSON
metode serialisasi Anda sendiri dengan logika untuk membuat serialisasi objek kustom Anda. Dengan demikian, Anda dapat dengan cepat dan mudah membangun dukungan serialisasi untuk hierarki objek yang lebih kompleks.
<SELECT MULTIPLE>
dan <INPUT type="checkbox">
dengan nama yang sama, dengan mengubah nilai menjadi array.
JSON.stringify(Object.fromEntries(formData));
jauh lebih baik
Pada 2019, tugas semacam ini menjadi sangat mudah.
JSON.stringify(Object.fromEntries(formData));
Object.fromEntries
: Didukung di Chrome 73+, Firefox 63+, Safari 12.1
<select multiple>
atau <input type="checkbox">
😞
JSON.stringify(Object.fromEntries(formData.entries()));
Berikut adalah cara melakukannya dengan gaya yang lebih fungsional, tanpa menggunakan perpustakaan.
Array.from(formData.entries()).reduce((memo, pair) => ({
...memo,
[pair[0]]: pair[1],
}), {});
Contoh:
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>
Jika Anda memiliki banyak entri dengan nama yang sama, misalnya jika Anda menggunakan <SELECT multiple>
atau memiliki banyak entri dengan nama <INPUT type="checkbox">
yang sama, Anda perlu menjaganya dan membuat array nilainya. Jika tidak, Anda hanya mendapatkan nilai yang terakhir dipilih.
Berikut adalah varian ES6 modern:
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 );
}
Kode yang sedikit lebih lama (tetapi masih tidak didukung oleh IE11, karena tidak mendukung ForEach
atau entries
aktif 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 );
}
Anda bisa mencapai ini dengan menggunakan objek FormData () . Objek FormData ini akan diisi dengan kunci / nilai formulir saat ini menggunakan properti nama setiap elemen untuk kunci dan nilai yang dikirimkan untuk nilai tersebut. Ini juga akan menyandikan konten masukan file.
Contoh:
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())
Fungsi Mudah Digunakan
Saya Telah Menciptakan Fungsi Untuk Ini
function FormDataToJSON(FormElement){
var formData = new FormData(FormElement);
var ConvertedJSON= {};
for (const [key, value] of formData.entries())
{
ConvertedJSON[key] = value;
}
return ConvertedJSON
}
Contoh Penggunaan
var ReceivedJSON = FormDataToJSON(document.getElementById('FormId');)
Dalam kode ini saya telah membuat variabel JSON kosong menggunakan for
loop yang telah saya gunakan key
dari Objek formData ke Kunci JSON di setiap Itration.
Anda Menemukan Kode Ini Di Perpustakaan JS Saya Di GitHub Sarankan Saya Jika Perlu Perbaikan, Saya Telah Menempatkan Kode Di Sini https://github.com/alijamal14/Utilities/blob/master/Utilities.js
<select multiple>
atau <input type="checkbox">
.
Postingan ini sudah berumur setahun ... tapi, saya sangat, sangat suka jawaban ES6 @dzuc. Namun ini tidak lengkap karena tidak dapat menangani beberapa kotak centang atau kotak centang. Ini telah menunjuk dan solusi kode telah ditawarkan. Saya merasa mereka berat dan tidak dioptimalkan. Jadi saya menulis 2 versi berdasarkan @dzuc untuk menangani kasus ini:
let r=Array.from(fd).reduce(
(o , [k,v]) => (
(!o[k])
? {...o , [k] : v}
: {...o , [k] : [...o[k] , v]}
)
,{}
);
let obj=JSON.stringify(r);
Versi Jagoan satu baris:
Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
[]
akhiran.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);
Versi Jagoan satu baris:
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}),{});
Sejak terakhir kali saya menulis kasus kedua sebelumnya, di tempat kerja muncul kasus bahwa formulir PHP memiliki kotak centang pada multi-level. Saya menulis kasus baru untuk mendukung kasus sebelumnya dan yang ini. Saya membuat cuplikan untuk memamerkan kasus ini dengan lebih baik, hasilnya ditampilkan di konsol untuk demo ini, ubah ini sesuai kebutuhan Anda. Mencoba mengoptimalkannya sebaik mungkin tanpa mengorbankan kinerja, namun, ini membahayakan beberapa keterbacaan manusia. Ini mengambil keuntungan bahwa array adalah objek dan variabel yang menunjuk ke array disimpan sebagai referensi. Tidak ada jagoan untuk yang satu ini, jadilah tamuku.
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}), {});
versi jagoan es2018
Metode FormData .entries
dan for of
ekspresi tidak didukung di IE11 dan Safari.
Ini adalah versi yang lebih sederhana untuk mendukung Safari, Chrome, Firefox dan Edge
function formDataToJSON(formElement) {
var formData = new FormData(formElement),
convertedJSON = {};
formData.forEach(function(value, key) {
convertedJSON[key] = value;
});
return convertedJSON;
}
Peringatan: jawaban ini tidak berfungsi di IE11.
FormData tidak memiliki forEach
metode di IE11.
Saya masih mencari solusi akhir untuk mendukung semua browser utama.
Jika Anda memerlukan dukungan untuk membuat serialisasi bidang bersarang, mirip dengan cara PHP menangani bidang formulir, Anda dapat menggunakan fungsi berikut
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>
Jika Anda menggunakan lodash, itu bisa dilakukan dengan singkat fromPairs
import {fromPairs} from 'lodash';
const object = fromPairs(Array.from(formData.entries()));
Anda bisa mencobanya
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);
}
Meskipun jawaban dari @dzuc sudah sangat bagus, Anda dapat menggunakan array destructuring (tersedia di browser modern atau dengan Babel) untuk membuatnya lebih elegan:
// 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,
}), {})
Satu kalimat yang melecehkan!
Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {});
Hari ini saya belajar firefox memiliki dukungan penyebaran objek dan penghancuran array!
Jika item berikut memenuhi kebutuhan Anda, Anda beruntung:
[['key','value1'], ['key2','value2']
(seperti yang diberikan FormData) menjadi key-> value object {key1: 'value1', key2: 'value2'}
dan mengubahnya menjadi string JSON.Berikut kode yang Anda perlukan:
const data = new FormData(document.querySelector('form'));
const json = JSON.stringify(Array.from(data).reduce((o,[k,v])=>(o[k]=v,o),{}));
Semoga ini bisa membantu seseorang.
Saya tidak melihat penyebutan metode FormData.getAll sejauh ini.
Selain mengembalikan semua nilai yang terkait dengan kunci yang diberikan dari dalam objek FormData, itu menjadi sangat sederhana menggunakan metode Object.fromEntries seperti yang ditentukan oleh orang lain di sini.
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)
])
)
Cuplikan beraksi
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>
Bekerja untuk saya
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>
atau<input type="checkbox">
Dalam bentuk kasus saya Data adalah data, basis api mengharapkan objek tetapi data berisi objek serta semua barang lainnya jadi saya mencoba data.value it works !!!
Saya datang terlambat di sini. Namun, saya membuat metode sederhana yang memeriksa input 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);
Saya harap ini membantu orang lain.
Anda dapat melakukan pekerjaan ini dengan mudah tanpa menggunakan sesuatu yang istimewa. Kode seperti di bawah ini sudah cukup.
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()
membantu? Mungkin Anda mencoba memperbaiki sesuatu yang mungkin dilakukan dengan cara lain?