HTML5 FormData nesnesini JSON'a nasıl dönüştürebilirim? Jquery olmadan ve FormData'daki yuvalanmış özellikleri bir nesne gibi işleme olmadan.
HTML5 FormData nesnesini JSON'a nasıl dönüştürebilirim? Jquery olmadan ve FormData'daki yuvalanmış özellikleri bir nesne gibi işleme olmadan.
Yanıtlar:
Doğrudan nesne forEach
üzerinde de kullanabilirsiniz FormData
:
var object = {};
formData.forEach(function(value, key){
object[key] = value;
});
var json = JSON.stringify(object);
Ve ES6 ok fonksiyonlarıyla aynı çözümü tercih edenler için :
var object = {};
formData.forEach((value, key) => object[key] = value);
var json = JSON.stringify(object);
Ve çoklu seçim listeleri veya birden fazla değere sahip diğer form öğeleri için destek isteyenler için (bu konuyla ilgili cevabın altında çok fazla yorum olduğundan, olası bir çözüm ekleyeceğim) :
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);
Burada basit bir çoklu seçim listesi ile bu yöntemin kullanımını gösteren bir Fiddle .
Burada bitenler için bir yan not olarak, form verilerini json'a dönüştürmenin amacı, onu bir XML HTTP isteği aracılığıyla bir sunucuya göndermekse, FormData
nesneyi dönüştürmeden doğrudan gönderebilirsiniz . Bu kadar basit:
var request = new XMLHttpRequest();
request.open("POST", "http://example.com/submitform.php");
request.send(formData);
Başvuru için MDN'de FormData Nesnelerini Kullanma konusuna da bakın :
Cevabımın altındaki yorumlardan birinde belirtildiği gibi, JSON stringify
yöntemi her tür nesne için kutudan çıkmaz. Hangi türlerin desteklendiği hakkında daha fazla bilgi için MDN belgelerinin Açıklama bölümüneJSON.stringify
başvurmak istiyorum .
Açıklamada ayrıca şu hususlardan bahsedilmektedir:
Değerin toJSON () yöntemi varsa, hangi verilerin serileştirileceğini tanımlamak sorumludur.
Bu toJSON
, özel nesnelerinizi serileştirme mantığıyla kendi serileştirme yönteminizi sağlayabileceğiniz anlamına gelir . Bunun gibi, daha karmaşık nesne ağaçları için hızlı ve kolay bir şekilde serileştirme desteği oluşturabilirsiniz.
<SELECT MULTIPLE>
ve <INPUT type="checkbox">
aynı adla bir diziye değerini dönüştürerek.
JSON.stringify(Object.fromEntries(formData));
çok daha güzel
2019'da bu tür görevler çok kolay hale geldi.
JSON.stringify(Object.fromEntries(formData));
Object.fromEntries
: Chrome 73+, Firefox 63+, Safari 12.1'de desteklenir
<select multiple>
veya <input type="checkbox">
😞'yi işlemez
JSON.stringify(Object.fromEntries(formData.entries()));
İşte bunu bir kütüphane kullanmadan daha işlevsel bir tarzda yapmanın bir yolu.
Array.from(formData.entries()).reduce((memo, pair) => ({
...memo,
[pair[0]]: pair[1],
}), {});
Misal:
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>
Aynı ada sahip birden fazla giriş varsa, kullanırsanız örneğin <SELECT multiple>
veya birden sahip <INPUT type="checkbox">
aynı isimde, bu özen ve değerin bir dizi yapmak gerekir. Aksi takdirde yalnızca son seçilen değeri alırsınız.
İşte modern ES6 varyantı:
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 );
}
Biraz daha eski kod (ancak desteklemediği ForEach
veya entries
açık olmadığı için hala IE11 tarafından desteklenmiyor 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 );
}
FormData () nesnesini kullanarak bunu başarabilirsiniz . Bu FormData nesnesi, anahtarlar için her öğenin name özelliği ve değerler için gönderilen değerleri kullanılarak formun geçerli anahtarları / değerleri ile doldurulur. Ayrıca dosya giriş içeriğini de kodlayacaktır.
Misal:
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())
Kullanımı Kolay İşlev
Bunun İçin Bir Fonksiyon Oluşturdum
function FormDataToJSON(FormElement){
var formData = new FormData(FormElement);
var ConvertedJSON= {};
for (const [key, value] of formData.entries())
{
ConvertedJSON[key] = value;
}
return ConvertedJSON
}
Örnek Kullanım
var ReceivedJSON = FormDataToJSON(document.getElementById('FormId');)
Bu kodda for
döngüyü kullanarak boş JSON değişkeni oluşturdum key
. Her Itration'da formData Object'ten JSON Keys'e kadar s kullandım .
Bu Kodu GitHub'daki JS Kitaplığımda Buluyorsunuz İyileştirme Gerekirse Bana Önerin Kodu Buraya Yerleştirdim https://github.com/alijamal14/Utilities/blob/master/Utilities.js
<select multiple>
veya birden çok seçilen değeri işlemez <input type="checkbox">
.
Bu gönderi zaten bir yaşında ... ama ES6 @dzuc cevabını gerçekten çok seviyorum. Ancak, birden çok seçim veya onay kutusu işlenemediği için eksiktir. Bu zaten işaret etti ve kod çözümleri sunuldu. Onları ağır buluyorum ve optimize edilmemiş buluyorum. Bu nedenle, bu durumları ele almak için @ dzuc'a dayalı 2 sürüm yazdım:
let r=Array.from(fd).reduce(
(o , [k,v]) => (
(!o[k])
? {...o , [k] : v}
: {...o , [k] : [...o[k] , v]}
)
,{}
);
let obj=JSON.stringify(r);
Tek satırlık Hotshot sürümü:
Array.from(fd).reduce((o,[k,v])=>((!o[k])?{...o,[k]:v}:{...o,[k]:[...o[k],v]}),{});
[]
son eki olması gereken PHP stili formlar için .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);
Tek satırlık Hotshot sürümü:
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}),{});
Geçen sefer önceki ikinci vakayı yazdığımdan beri, işte PHP formunun çoklu seviyelerde onay kutularına sahip olduğu bir durum geldi. Önceki vakayı ve bunu desteklemek için yeni bir vaka yazdım. Bu davayı daha iyi sergilemek için bir pasaj oluşturdum, sonuç bu demo için konsolda gösterilir, bunu ihtiyacınıza göre değiştirin. Performanstan ödün vermeden yapabildiğim en iyi şekilde optimize etmeye çalıştım, ancak bazı insan okunabilirliğini tehlikeye attı. Dizilerin nesneler olması ve dizilere işaret eden değişkenlerin referans olarak tutulması avantajını kullanır. Bunun için önemli bir şey yok, konuğum ol.
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 version es2018
FormData yöntemi .entries
ve for of
ifade , IE11 ve Safari'de desteklenmez .
Safari, Chrome, Firefox ve Edge'i desteklemek için daha basit bir sürüm burada
function formDataToJSON(formElement) {
var formData = new FormData(formElement),
convertedJSON = {};
formData.forEach(function(value, key) {
convertedJSON[key] = value;
});
return convertedJSON;
}
Uyarı: bu cevap IE11'de çalışmıyor.
FormData'nın IE11'de bir forEach
yöntemi yoktur.
Hala tüm büyük tarayıcıları desteklemek için nihai bir çözüm arıyorum.
PHP'nin form alanlarını işleme biçimine benzer şekilde, iç içe geçmiş alanları serileştirmek için desteğe ihtiyacınız varsa, aşağıdaki işlevi kullanabilirsiniz
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>
Lodash kullanıyorsanız, bunu kısaca yapabilirsiniz. fromPairs
import {fromPairs} from 'lodash';
const object = fromPairs(Array.from(formData.entries()));
Bunu deneyebilirsin
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);
}
@Dzuc'un cevabı zaten çok iyi olsa da, onu biraz daha zarif hale getirmek için dizi yok etmeyi (modern tarayıcılarda veya Babel'de mevcut) kullanabilirsiniz:
// 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,
}), {})
Kötü niyetli tek satırlık!
Array.from(fd).reduce((obj, [k, v]) => ({...obj, [k]: v}), {});
Bugün firefox'un nesne yayma desteği ve dizi yıkımı olduğunu öğrendim!
Aşağıdaki öğeler ihtiyaçlarınızı karşılıyorsa, şanslısınız:
[['key','value1'], ['key2','value2']
(FormData'nın size verdiği gibi) benzeri bir anahtar-> değer nesnesine {key1: 'value1', key2: 'value2'}
dönüştürmek ve onu bir JSON dizesine dönüştürmek istiyorsunuz.İşte ihtiyacınız olacak kod:
const data = new FormData(document.querySelector('form'));
const json = JSON.stringify(Array.from(data).reduce((o,[k,v])=>(o[k]=v,o),{}));
Umarım bu birine yardımcı olur.
Şimdiye kadar FormData.getAll yönteminden hiç bahsetmedim .
FormData nesnesinin içinden belirli bir anahtarla ilişkili tüm değerleri döndürmenin yanı sıra, burada başkaları tarafından belirtildiği gibi Object.fromEntries yöntemini kullanarak gerçekten basitleşir .
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)
])
)
Snippet iş başında
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>
Benim için çalıştı
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>
Veya birden fazla seçilen değeri işlemez<input type="checkbox">
Benim durumumda Veri veri idi, yangın üssü bir nesne bekliyordu ancak veriler nesnenin yanı sıra diğer tüm şeyleri içeriyor, bu yüzden veriyi denedim. İşe yaradı !!!
Buraya geç geliyorum. Ancak, input type = "checkbox" ı kontrol eden basit bir yöntem yaptı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);
Umarım bu başkasına yardımcı olur.
Bu işi özel bir şey kullanmadan rahatlıkla yapabilirsiniz. Aşağıdaki gibi bir kod yeterli olacaktır.
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()
olur mu? Belki başka bir şekilde yapılabilecek bir şeyi onarmaya çalışırsınız?