Form verilerini jQuery ile JavaScript nesnesine dönüştürme


1624

Formumdaki tüm öğeleri bir JavaScript nesnesine nasıl dönüştürebilirim?

Her öğenin üzerinde döngü oluşturmadan formumdan otomatik olarak bir JavaScript nesnesi oluşturmanın bir yolunu istiyorum. Tarafından döndürülen bir dize istemiyorum $('#formid').serialize();, ne de harita tarafından döndürülen istiyorum$('#formid').serializeArray();


16
çünkü ilki, formu bir GET yöntemiyle gönderirseniz alacağınız gibi bir dize döndürür ve ikincisi size her biri bir ad değeri çiftine sahip bir dizi nesne verir. Ben "e-posta" adlı bir alan varsa bana obj.email ile bu değeri almak için izin verecek bir nesne olsun istiyorum. SerializeArray () ile, i obj böyle bir şey yapmak olurdu [indexOfElement] .value
Yisroel

2
@James - D. Crockford'un JSON-js kütüphanesini kullanarak kabul edilen cevap. İşte bir örnek: github.com/tleese22/google-app-engine-jappstart/blob/master/src/…
Taylor Leese

4
@Taylor Evet, doğru cevabın Crockford'un lib ve Tobias işlevini şu şekilde kullandığını söyleyebilirim: JSON.stringify ($ ('myForm'). SerializeObject ())
James McCormack

5
@Jonz - Form öğesi kullanmak için gönderme / iletmenin yanı sıra başka nedenler de var. JavaScript içindeki form değerleriyle (örneğin, tek sayfa uygulaması) ağır bir kaldırma işlemi yapıyorsanız, bunlara erişmek ve değiştirmek için nesne biçiminde olması çok kullanışlıdır. Ayrıca, HTTP Post ve Get sorgu dizeleri, verileri hareket ettirmek için tek biçim değildir.
Patrick M

3
İyi bir js ı >> rastladım github.com/marioizquierdo/jquery.serializeJSON
Bongs

Yanıtlar:


1657

serializeArrayzaten bunu yapıyor. Sadece verileri gerekli formatta masaj yapmanız yeterlidir:

function objectifyForm(formArray) {//serialize data function

  var returnArray = {};
  for (var i = 0; i < formArray.length; i++){
    returnArray[formArray[i]['name']] = formArray[i]['value'];
  }
  return returnArray;
}

Üzerine yazılacakları gerçek girdilerle aynı ada sahip gizli alanlara dikkat edin.


4
tvanfosson'un dediği gibi, koleksiyonu neden iki kez yineliyorsunuz?
Yisroel

69
"Neden ilk etapta veri almak için serializeArray kullanıyorsunuz?" SerializeArray zaten yazılmış olduğundan, birden fazla tarayıcıda birim test edilmiştir ve jQuery'nin sonraki sürümlerinde teorik olarak geliştirilebilir. DOM öğeleri gibi tutarsız şeylere doğrudan erişmek zorunda kaldığınızda ne kadar az kod yazarsanız, kodunuz o kadar kararlı olur.
Tobias Cohen

56
Dikkat edin, serializeArray () devre dışı bırakılmış öğeler içermez. Sıklıkla sayfadaki diğer öğelerle senkronize edilen giriş öğelerini devre dışı bırakıyorum, ancak yine de bunların serileştirilmiş nesneme dahil edilmesini istiyorum. $.map( $("#container :input"), function(n, i) { /* n.name and $(n).val() */ } );Devre dışı bırakılmış öğeler eklemeniz gerekiyorsa gibi bir şey kullanmanız daha iyi olur.
Samuel Meacham

22
@TobiasCohen foo[bar]Diğer girdi adı çeşitlerinin çoğundan bahsetmemek için beklendiği gibi -tip girdileri işlemez . Bu soruna sığ çözümler ile çok sinirli olduktan sonra, kendi jQuery eklentimi yazdım - bu soruya verdiğim cevapta ayrıntılar.
maček

6
@macek Bunun birkaç aylık olduğunu biliyorum, ancak diziler ne zamandan beri sayısal olmayan dizinler kullandılar? Hiç kimse bir giriş foo [bar] olarak adlandırmamalı ve onu bir dizi olarak ele almayı ummamalıdır. Dizileri ve karmaları karıştırıyor musunuz? Evet, [] genellikle diziler için değil, bir erişimci olarak anlaşılmaktadır. Ayrıca geçerli HTML olduğunu ancak HTML özelliklerinde olmadığını söylemek de bir çelişkidir. Evet, tarayıcı bunu boğmayabilir, ancak pek çok web sunucusu diziyi nasıl atayacağını nasıl bileceğini bilemez. Neden? Çünkü HTML özelliklerinde değil. Bu nedenle, aslında geçersiz.
kroehre

446

Formları patron gibi JSON'a dönüştürme


Geçerli kaynak GitHub ve Bower üzerindedir .

$ bower install jquery-serialize-object


Aşağıdaki kod artık kullanımdan kaldırıldı .

Aşağıdaki kod, her türlü giriş adıyla çalışabilir; ve beklediğiniz gibi halledin.

Örneğin:

<!-- All of these will work! -->
<input name="honey[badger]" value="a">
<input name="wombat[]" value="b">
<input name="hello[panda][]" value="c">
<input name="animals[0][name]" value="d">
<input name="animals[0][breed]" value="e">
<input name="crazy[1][][wonky]" value="f">
<input name="dream[as][vividly][as][you][can]" value="g">
// Output
{
  "honey":{
    "badger":"a"
  },
  "wombat":["b"],
  "hello":{
    "panda":["c"]
  },
  "animals":[
    {
      "name":"d",
      "breed":"e"
    }
  ],
  "crazy":[
    null,
    [
      {"wonky":"f"}
    ]
  ],
  "dream":{
    "as":{
      "vividly":{
        "as":{
          "you":{
            "can":"g"
          }
        }
      }
    }
  }
}

kullanım

$('#my-form').serializeObject();

Büyücülük (JavaScript)

(function($){
    $.fn.serializeObject = function(){

        var self = this,
            json = {},
            push_counters = {},
            patterns = {
                "validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
                "key":      /[a-zA-Z0-9_]+|(?=\[\])/g,
                "push":     /^$/,
                "fixed":    /^\d+$/,
                "named":    /^[a-zA-Z0-9_]+$/
            };


        this.build = function(base, key, value){
            base[key] = value;
            return base;
        };

        this.push_counter = function(key){
            if(push_counters[key] === undefined){
                push_counters[key] = 0;
            }
            return push_counters[key]++;
        };

        $.each($(this).serializeArray(), function(){

            // Skip invalid keys
            if(!patterns.validate.test(this.name)){
                return;
            }

            var k,
                keys = this.name.match(patterns.key),
                merge = this.value,
                reverse_key = this.name;

            while((k = keys.pop()) !== undefined){

                // Adjust reverse_key
                reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');

                // Push
                if(k.match(patterns.push)){
                    merge = self.build([], self.push_counter(reverse_key), merge);
                }

                // Fixed
                else if(k.match(patterns.fixed)){
                    merge = self.build([], k, merge);
                }

                // Named
                else if(k.match(patterns.named)){
                    merge = self.build({}, k, merge);
                }
            }

            json = $.extend(true, json, merge);
        });

        return json;
    };
})(jQuery);

17
Yani, bu oldukça iyi çalışıyor. Ancak adı yanlıştır: adından da anlaşılacağı gibi JSON döndürmez. Bunun yerine, bir nesne değişmez değeri döndürür. Ayrıca, hasOwnProperty'yi kontrol etmek önemlidir, aksi takdirde dizilerinizin prototiplerine eklenmiş herhangi bir şeyi vardır: {numbers: ["1", "3", indexOf: function () {...}]}
frontendbeauty

5
@frontendbeauty aslında, toJSON spesifikasyonun tam olarak adlandırılması gerektiğini söylediği şeydir: developer.mozilla.org/en/JSON#toJSON()_method talihsiz bir yanlış isim.
Ryan Florence

4
@Marek, burada jsfiddle üzerinde bir test yaptım . İşin püf noktası, seçiminizi doğru bir şekilde adlandırmaktır. <select name="foo" multiple="multiple">hiçbir senaryoda çalışmaz. Ancak, kullanırsanız [], olduğu gibi <select name="bar[]" multiple="multiple">, iyi çalışır :)
maček

3
Github.com/serbanghita/formToObject öğesinin aynı işi yapan benzer bir JavaScript yöntemi (3. taraf kitaplığı gerekmez) olduğunu belirtmek istedim . 'Çoklu' desteği, 'devre dışı' öğeleri yok sayar.
banerban Ghiță

8
Bu çözüm, form öğesi adları olarak iç içe anahtarlarla ilgili sorunu ele aldığı için en üstte olmalıdır.
SquareCat

283

Sorun ne:

var data = {};
$(".form-selector").serializeArray().map(function(x){data[x.name] = x.value;}); 

2
@LayZee - hiçbir şey seçilmezse, neden arka ucunuzda olmasını istersiniz? bir seçenek belirlemeniz gerekiyorsa, serileştirmeden önce girişi doğrulayın.
Dementic

21
bir şey iade etmiyorsanız, neden sadece .eachyerine kullanmıyorsunuz .map??
azerafati

10
Çok basit çünkü süper saf ... aynı adı taşıyan onay kutularını işlemiyor. Her seferinde kontrol edilen öğeyi ondan önce geçersiz kılacaktır. Doğru şekilde serileştirildiğinden emin olmak için kesinlikle bazı giriş türü algılamanız gerekir.
Joshua F. Rountree

5
Saf bir jQuery çözümü istiyorsanız, kullanabilirsinizvar form = {}; $.each($(this).serializeArray(), function (i, field) { form[field.name] = field.value || ""; });
tfmontague

42
$(this).serializeArray().reduce(function(m,o){ m[o.name] = o.value; return m;}, {})
siteler

103

Tobias Cohen'in çözümünün sabit bir versiyonu. Bu, 0ve gibi falsy değerlerini doğru şekilde işler ''.

jQuery.fn.serializeObject = function() {
  var arrayData, objectData;
  arrayData = this.serializeArray();
  objectData = {};

  $.each(arrayData, function() {
    var value;

    if (this.value != null) {
      value = this.value;
    } else {
      value = '';
    }

    if (objectData[this.name] != null) {
      if (!objectData[this.name].push) {
        objectData[this.name] = [objectData[this.name]];
      }

      objectData[this.name].push(value);
    } else {
      objectData[this.name] = value;
    }
  });

  return objectData;
};

Kodlama rahatlığınız için bir CoffeeScript sürümü:

jQuery.fn.serializeObject = ->
  arrayData = @serializeArray()
  objectData = {}

  $.each arrayData, ->
    if @value?
      value = @value
    else
      value = ''

    if objectData[@name]?
      unless objectData[@name].push
        objectData[@name] = [objectData[@name]]

      objectData[@name].push value
    else
      objectData[@name] = value

  return objectData

Coffeescript'te, eğer ilk blok kısaltılabilirsevalue = @value ? ''
nzifnab

Rails benzeri formları serileştirmeye çalışıyorsanız, oluşturulan anahtarlardan öğe kökünü kaldırmak isteyebilirsiniz. Bunu başarmak için, yeni bir param ekledik keyMapve aşağıdaki satırı: key = if keyMap? then keyMap(@name) else @name. Artık haritalama fonksiyonunu geçebilirsiniz (name) -> name.match(/\[([^\]]+)]/)[1]. Ve sonra bir sonraki tüm değiştirmeniz gerekir @nameiçin keyelbette
Damir ZEKIC

@ DamirZekić, eğer kök öğeniz olsaydı post, bunu yapabilirdiniz $('form').serializeObject().post. Süslü haritalamaya gerek yok.
maček

@ DamirZekić Bu hat ne yapıyor? if (!objectData[this.name].push)??
kittu

@kittu objectData[this.name]Push yöntemi olup olmadığını kontrol ediyor (kabaca bir dizi mi). Bir dizi ise, değeri iter, eğer bir dizi değilse, onu bir diziye dönüştürür, böylece aynı tuşa sahip birden çok değer bir diziyle birleştirilir.
Daniel X Moore

63

Kullanmayı seviyorum Array.prototype.reduceçünkü tek astarlı ve Underscore.js veya benzeri bir şeye dayanmıyor :

$('#formid').serializeArray()
    .reduce(function(a, x) { a[x.name] = x.value; return a; }, {});

Bu, yanıtı kullanmaya benzer Array.prototype.map, ancak kapsamınızı ek bir nesne değişkeni ile karıştırmanıza gerek yoktur. Tek elden alışveriş.

ÖNEMLİ NOT : Yinelenen nameözniteliklere sahip girişlere sahip formlar geçerli HTML'dir ve aslında ortak bir yaklaşımdır. Bu durumda cevaplardan herhangi birini kullanmak bu durumda uygunsuz olacaktır (çünkü nesne anahtarları benzersiz olmalıdır).


Bu oldukça zarif. Ancak array.prototype.reduce(), ECMAScript 5 spesifikasyonunun bir parçası olduğu için IE8'de mevcut olmadığını belirtmek gerekir . Yani IE8 desteğine ihtiyacınız varsa, bir çoklu dolgu veya başka bir çözüm kullanmak istersiniz .
gfullam

3
Doğru, ancak çoklu doldurmak için yeterince kolay. Ayrıca, IE8 baş ağrısı neredeyse bitti, Microsoft'un IE11 Enterprise Mode ile yaptığı büyük çalışma sayesinde - IE8 kullanan bireysel kullanıcılara artık hitap etmiyorum, ancak IE8 kullanan 10.000 çalışanı olan bir kuruluş geldiğinde ... bu farklı. Neyse ki, Microsoft bu sorun üzerinde çok çalışıyor.
Ethan Brown

1
BT çalışanlarınızın IE11 Enterprise moduna bakmasını sağlamalısınız - modern bir tarayıcı ve IE8 uyumlu uygulamaları çalıştırmanın bir yolunu sunar. Microsoft'un akıllıca
Ethan Brown

30

Tüm bu cevaplar benim için çok üstte görünüyordu. Basitlik için söylenecek bir şey var. Tüm form girişleriniz name özniteliğine sahip olduğu sürece bu sadece jim dandy ile çalışmalıdır.

$('form.myform').submit(function () {
  var $this = $(this)
    , viewArr = $this.serializeArray()
    , view = {};

  for (var i in viewArr) {
    view[viewArr[i].name] = viewArr[i].value;
  }

  //Do stuff with view object here (e.g. JSON.stringify?)
});

4
İç içe form verilerini işlemez, bu yüzden cevaplar daha karmaşık hale gelir.
frontendbeauty

Benim için harika çalıştı. Sadece anahtar / değer çiftlerinin depolanması gerekiyor; stringSize ve daha sonra localStorage veya çerez kaydetmek sadece züppe çalıştı.
Greg Pettit

23

Her bir unsuru incelemeden bunu yapmanın gerçekten bir yolu yoktur. Gerçekten bilmek istediğiniz şey, "bir başkası formu JSON nesnesine dönüştüren bir yöntem zaten yazmış mı?" Aşağıdaki gibi bir şey işe yarayacaktır - bunun size yalnızca bir POST aracılığıyla döndürülecek form öğelerini vereceğini unutmayın (bir adı olmalıdır). Bu test edilmedi .

function formToJSON( selector )
{
     var form = {};
     $(selector).find(':input[name]:enabled').each( function() {
         var self = $(this);
         var name = self.attr('name');
         if (form[name]) {
            form[name] = form[name] + ',' + self.val();
         }
         else {
            form[name] = self.val();
         }
     });

     return form;
}

doğru, bunu benim için yapacak bir eklentiyi çok isterdim. bir isme sahip olmanın sınırlandırılması önemli değildir. bu, textareas ve selected dahil tüm alanları bir formda çekecek mi?
Yisroel

[devre dışı] için hesap oluşturmak isteyip istemediğinizden emin değilim, ancak bunun gönderilmesi / alınması gerektiğini düşünmüyorum.
meder omuraliev

harita almak için serializeArray () kullanmak daha basit olabilir ve daha sonra normal bir JSON nesnesi dönüştürmek için yukarıdakine benzer kodu kullanın, bu şekilde formun kendisi ile ilgilenmiyorum
Yisroel

2
SerializedArray kullanmak işe yarayacaktır, ancak temelde koleksiyonu iki kez yineleyeceksiniz - bir kez dizi üretmek için, sonra dizi üzerinde. Buna ihtiyacım yok.
tvanfosson

Seçiciyi etkin / devre dışı olarak ayarlayacağım.
tvanfosson

23

Eğer kullanıyorsanız Underscore.js nispeten kısa ve öz kullanabilirsiniz:

_.object(_.map($('#myform').serializeArray(), _.values))

19

Diğer tüm cevaplarda bir sorun olduğunu kontrol ettim, eğer giriş adı gibi bir dizi ise name[key], o zaman böyle üretilmelidir:

name:{ key : value }


Örneğin: Aşağıdakine benzer bir HTML formunuz varsa:

<form>
    <input name="name" value="value" >
    <input name="name1[key1]" value="value1" >
    <input name="name2[key2]" value="value2" >
    <input name="name3[key3]" value="value3" >
</form>

Ancak aşağıdaki JSON gibi üretilmelidir ve diğer tüm cevaplarla aşağıdaki gibi bir nesne haline gelmez. Eğer birisi aşağıdaki JSON gibi bir şey getirmek isterse, aşağıdaki JS kodunu deneyin.

{
    name  : 'value',
    name1 : { key1 : 'value1' },
    name2 : { key2 : 'value2' },
    name3 : { key2 : 'value2' }
}

$.fn.getForm2obj = function() {
  var _ = {};
  $.map(this.serializeArray(), function(n) {
    const keys = n.name.match(/[a-zA-Z0-9_]+|(?=\[\])/g);
    if (keys.length > 1) {
      let tmp = _;
      pop = keys.pop();
      for (let i = 0; i < keys.length, j = keys[i]; i++) {
        tmp[j] = (!tmp[j] ? (pop == '') ? [] : {} : tmp[j]), tmp = tmp[j];
      }
      if (pop == '') tmp = (!Array.isArray(tmp) ? [] : tmp), tmp.push(n.value);
      else tmp[pop] = n.value;
    } else _[keys.pop()] = n.value;
  });
  return _;
}
console.log($('form').getForm2obj());
$('form input').change(function() {
  console.clear();
  console.log($('form').getForm2obj());
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<form>
  <input name="name" value="value">
  <input type="checkbox" name="name1[]" value="1" checked="checked">1
  <input type="checkbox" name="name1[]" value="2">2
  <input type="checkbox" name="name1[]" value="3">3<br>
  <input type="radio" name="gender" value="male" checked="checked">male
  <input type="radio" name="gender" value="female"> female
  <input name="name2[key1]" value="value1">
  <input name="one[another][another_one]" value="value4">
  <input name="name3[1][name]" value="value4">
  <input name="name3[2][name]" value="value4">
  <input name="[]" value="value5">
</form>


Bu yanıt belirtilen vakayı kapsamaktadır, ancak onay kutusu [] veya hatta bir [başka] [another_one] gibi vakaları kapsamaz
Leonardo Beal

1
@LeonardoBeal ans düzeltmek .. şimdi kontrol edin ..!
Bhavik Hirani

Ben downvoter'ım ve aşağı indirildim çünkü evalbu şekilde kullanılmamalıyım, çünkü bu şekilde evalkullanıldığında korkunç derecede güvenilmez, buggy, kötü niyetli ve potansiyel olarak güvenli olmayan uygulamaları teşvik eder.
Jack Giffin

2
Bunun iyi bir cevap olduğunu kabul edemem. Ve lütfen cevap yazarken kodunuzu açıklayıcı hale getirin veya açıklayın. this.c = function(k,v){ eval("c = typeof "+k+";"); if(c == 'undefined') _t.b(k,v);}kısa ve açıklayıcı değil. Daha az deneyime sahip bir geliştirici, bunu neden ve nasıl çalıştığını anlamadan kopyalayacaktır.
iRaS

2
@JackGiffin Yeni kodumu şimdi kontrol et çünkü kodumdan kaldırdım eval().
Bhavik Hirani

17

Tamam, bunun zaten son derece onaylanmış bir cevabı olduğunu biliyorum, ancak son zamanlarda benzer bir soru daha soruldu ve ben de bu soruya yönlendirildim. Çözümümü de sunmak istiyorum, çünkü kabul edilen çözüme göre bir avantaj sunuyor: Devre dışı bırakılmış form öğelerini dahil edebilirsiniz (bu, bazen kullanıcı arayüzünüzün işlevine bağlı olarak önemlidir)

İşte diğer SO sorusundan cevabım :

Başlangıçta, jQuery'nin serializeArray()yöntemini kullanıyorduk , ancak bu devre dışı bırakılmış form öğelerini içermiyor. Sıklıkla sayfadaki diğer kaynaklarla "senkronize edilen" form öğelerini devre dışı bırakırız, ancak yine de verileri serileştirilmiş nesnemize dahil etmemiz gerekir. Öyleyse serializeArray()çıktı. :inputBelirli bir kapsayıcıdaki tüm giriş öğelerini (hem etkin hem de devre dışı) almak ve sonra $.map()nesneyi oluşturmak için seçiciyi kullandık .

var inputs = $("#container :input");
var obj = $.map(inputs, function(n, i)
{
    var o = {};
    o[n.name] = $(n).val();
    return o;
});
console.log(obj);

Bunun çalışması için, girdilerinizin her birinin namesonuçta ortaya çıkan nesnenin özelliğinin adı olacak bir niteliğe ihtiyacı olacağını unutmayın.

Bu aslında kullandığımızdan biraz değiştirildi. Bir .NET IDictionary olarak yapılandırılmış bir nesne yaratmamız gerekiyordu, bu yüzden bunu kullandık: (Yararlı olması durumunda burada sağlıyorum)

var obj = $.map(inputs, function(n, i)
{
    return { Key: n.name, Value: $(n).val() };
});
console.log(obj);

Bu çözümlerin her ikisini de seviyorum, çünkü bunlar $.map()fonksiyonun basit kullanımlarıdır ve seçiciniz üzerinde tam bir kontrole sahipsiniz (yani, sonuçta ortaya çıkan nesneye dahil ettiğiniz öğeleri). Ayrıca, ek bir eklenti gerekmez. Düz eski jQuery.


6
Bu bir projede denedim, mapböyle kullanarak tek bir özelliği olan nesneler dizisi oluşturur, tüm özellikleri tek bir nesneye daraltmaz.
joshperry

16

Bu işlev, aynı ada sahip birden çok öğeyle birlikte çok boyutlu dizileri işlemelidir.

Şimdiye kadar birkaç yıldır kullanıyorum:

jQuery.fn.serializeJSON=function() {
  var json = {};
  jQuery.map(jQuery(this).serializeArray(), function(n, i) {
    var _ = n.name.indexOf('[');
    if (_ > -1) {
      var o = json;
      _name = n.name.replace(/\]/gi, '').split('[');
      for (var i=0, len=_name.length; i<len; i++) {
        if (i == len-1) {
          if (o[_name[i]]) {
            if (typeof o[_name[i]] == 'string') {
              o[_name[i]] = [o[_name[i]]];
            }
            o[_name[i]].push(n.value);
          }
          else o[_name[i]] = n.value || '';
        }
        else o = o[_name[i]] = o[_name[i]] || {};
      }
    }
    else {
      if (json[n.name] !== undefined) {
        if (!json[n.name].push) {
          json[n.name] = [json[n.name]];
        }
        json[n.name].push(n.value || '');
      }
      else json[n.name] = n.value || '';      
    }
  });
  return json;
};

15

Bunu yapabilirsiniz:

var frm = $(document.myform);
var data = JSON.stringify(frm.serializeArray());

Bkz. JSON .


14

Tek astar (jQuery dışında bağımlılık yok), mapyönteme iletilen işlev için sabit nesne bağlaması kullanır .

$('form').serializeArray().map(function(x){this[x.name] = x.value; return this;}.bind({}))[0]

Bu ne yapar?

"id=2&value=1&comment=ok" => Object { id: "2", value: "1", comment: "ok" }

aşamalı web uygulamaları için uygun (hem normal form gönderme eylemini hem de ajax isteklerini kolayca destekleyebilir)


12

kullanın:

function form_to_json (selector) {
  var ary = $(selector).serializeArray();
  var obj = {};
  for (var a = 0; a < ary.length; a++) obj[ary[a].name] = ary[a].value;
  return obj;
}

Çıktı:

{"myfield": "myfield value", "passwordfield": "mypasswordvalue"}

7

Sadelik burada en iyisidir. Ben normal bir ifade ile basit bir dize yerine kullandım ve şimdiye kadar bir cazibe gibi çalıştı. Düzenli bir ifade uzmanı değilim, ama çok karmaşık nesneleri bile doldurabileceğinize eminim.

var values = $(this).serialize(),
attributes = {};

values.replace(/([^&]+)=([^&]*)/g, function (match, name, value) {
    attributes[name] = value;
});

7

Bazı eski cevaplardan:

$('form input, form select').toArray().reduce(function(m,e){m[e.name] = $(e).val(); return m;},{})

Söyleyebileceğim kadarıyla, fark, çözümünüzün bağlı olmamasıdır, serializeArrayböylece istediğiniz herhangi bir girdiyi seçme özgürlüğüne sahip olursunuz (örneğin, devre dışı girdileri dahil edebilirsiniz), değil mi? Yani bu herhangi bir formata ya da boyun eğme olayına bağlı değil, tek başına bağımsız mı?
dvtan

bağlantılı cevabı olan tek küçük fark reduce, nesneyi başlatmak için gerekli veri olmamasıdır . Bu bağımsız değildir çünkü toArrayjQuery'den.
siteler

6

Tobias Cohen'in koduyla ilgili bir sorun buldum (doğrudan yorum yapmak için yeterli puanım yok), aksi takdirde benim için çalışıyor. Aynı ada sahip, her ikisi de = "" değerine sahip iki seçim seçeneğiniz varsa, orijinal kod "name" yerine "name": "" üretir: ["", ""]

Bunun ilk if koşuluna "|| o [this.name] == ''" eklenerek düzeltilebileceğini düşünüyorum:

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] || o[this.name] == '') {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

6

Maček'in çözümünü kullanarak, ASP.NET MVC'nin iç içe / karmaşık nesnelerini aynı formda işleme biçimiyle çalışacak şekilde değiştirdim. Tek yapmanız gereken doğrulama parçasını buna göre değiştirmek:

"validate": /^[a-zA-Z][a-zA-Z0-9_]*((?:\[(?:\d*|[a-zA-Z0-9_]+)\])*(?:\.)[a-zA-Z][a-zA-Z0-9_]*)*$/,

Bu, aşağıdaki gibi adlarla öğeleri eşleştirecek ve doğru şekilde eşleyecektir:

<input type="text" name="zooName" />

Ve

<input type="text" name="zooAnimals[0].name" />



4
const formData = new FormData(form);

let formDataJSON = {};

for (const [key, value] of formData.entries()) {

    formDataJSON[key] = value;
}

3

Bu yaklaşımı tercih ediyorum, çünkü: 2'den fazla koleksiyon yinelemeniz gerekmez, ihtiyacınız varsa "isim" ve "değer" dışında bir şey elde edebilirsiniz ve değerlerinizi nesneye kaydetmeden önce dezenfekte edebilirsiniz ( saklamak istemediğiniz varsayılan değerleriniz varsa).

$.formObject = function($o) {
    var o = {},
        real_value = function($field) {
            var val = $field.val() || "";

            // additional cleaning here, if needed

            return val;
        };

    if (typeof o != "object") {
        $o = $(o);
    }

    $(":input[name]", $o).each(function(i, field) {
        var $field = $(field),
            name = $field.attr("name"),
            value = real_value($field);

        if (o[name]) {
            if (!$.isArray(o[name])) {
                o[name] = [o[name]];
            }

            o[name].push(value);
        }

        else {
            o[name] = value;
        }
    });

    return o;
}

Şöyle kullanın:

var obj = $.formObject($("#someForm"));

Yalnızca Firefox'ta test edildi.


3

Herhangi bir şeyi bir nesneye dönüştürün (test edilmiş birim değil)

<script type="text/javascript">
string = {};

string.repeat = function(string, count)
{
    return new Array(count+1).join(string);
}

string.count = function(string)
{
    var count = 0;

    for (var i=1; i<arguments.length; i++)
    {
        var results = string.match(new RegExp(arguments[i], 'g'));
        count += results ? results.length : 0;
    }

    return count;
}

array = {};

array.merge = function(arr1, arr2)
{
    for (var i in arr2)
    {
        if (arr1[i] && typeof arr1[i] == 'object' && typeof arr2[i] == 'object')
            arr1[i] = array.merge(arr1[i], arr2[i]);
        else
            arr1[i] = arr2[i]
    }

    return arr1;
}

array.print = function(obj)
{
    var arr = [];
    $.each(obj, function(key, val) {
        var next = key + ": ";
        next += $.isPlainObject(val) ? array.print(val) : val;
        arr.push( next );
      });

    return "{ " +  arr.join(", ") + " }";
}

node = {};

node.objectify = function(node, params)
{
    if (!params)
        params = {};

    if (!params.selector)
        params.selector = "*";

    if (!params.key)
        params.key = "name";

    if (!params.value)
        params.value = "value";

    var o = {};
    var indexes = {};

    $(node).find(params.selector+"["+params.key+"]").each(function()
    {
        var name = $(this).attr(params.key),
            value = $(this).attr(params.value);

        var obj = $.parseJSON("{"+name.replace(/([^\[]*)/, function()
        {
            return '"'+arguments[1]+'"';
        }).replace(/\[(.*?)\]/gi, function()
        {
            if (arguments[1].length == 0)
            {
                var index = arguments[3].substring(0, arguments[2]);
                indexes[index] = indexes[index] !== undefined ? indexes[index]+1 : 0;

                return ':{"'+indexes[index]+'"';
            }
            else
                return ':{"'+escape(arguments[1])+'"';
        })+':"'+value.replace(/[\\"]/gi, function()
        {
            return "\\"+arguments[0]; 
        })+'"'+string.repeat('}', string.count(name, ']'))+"}");

        o = array.merge(o, obj);
    });

    return o;
}
</script>

Testin çıktısı:

$(document).ready(function()
{
    console.log(array.print(node.objectify($("form"), {})));
    console.log(array.print(node.objectify($("form"), {selector: "select"})));
});

üzerinde

<form>
    <input name='input[a]' type='text' value='text'/>
    <select name='input[b]'>
        <option>select</option>
    </select>

    <input name='otherinput[c][a]' value='a'/>
    <input name='otherinput[c][]' value='b'/>
    <input name='otherinput[d][b]' value='c'/>
    <input name='otherinput[c][]' value='d'/>

    <input type='hidden' name='anotherinput' value='hidden'/>
    <input type='hidden' name='anotherinput' value='1'/>

    <input type='submit' value='submit'/>
</form>

getirecek:

{ input: { a: text, b: select }, otherinput: { c: { a: a, 0: b, 1: d }, d: { b: c } }, anotherinput: 1 }
{ input: { b: select } }

3

Seçilen çözümle ilgili bir sorun buldum.

Dizi tabanlı isimlere sahip formları kullanırken jQuery serializeArray () işlevi gerçekten ölür.

Aynı form birden çok görünümde birden çok kez aynı sayfaya koymak için dizi tabanlı alan adları kullanan bir PHP çerçeve var. Bu, çakışan form modelleri olmadan aynı sayfaya hem ekleme, düzenleme hem de silme işlemi yapmak için kullanışlı olabilir.

Ben bu mutlak temel işlevselliği dışarı almak zorunda kalmadan formları seralize etmek istedim beri kendi seralizeArray () yazmaya karar verdim:

        var $vals = {};

        $("#video_edit_form input").each(function(i){
            var name = $(this).attr("name").replace(/editSingleForm\[/i, '');

            name = name.replace(/\]/i, '');

            switch($(this).attr("type")){
                case "text":
                    $vals[name] = $(this).val();
                    break;
                case "checkbox":
                    if($(this).attr("checked")){
                        $vals[name] = $(this).val();
                    }
                    break;
                case "radio":
                    if($(this).attr("checked")){
                        $vals[name] = $(this).val();
                    }
                    break;
                default:
                    break;
            }
        });

Lütfen dikkat: Bu, form send () yönteminin dışında da çalışır, bu nedenle kodunuzun geri kalanında bir hata oluşursa "değişiklikleri kaydet" yazan bir bağlantı düğmesine yerleştirirseniz form gönderilmez.

Ayrıca, bu işlevin, yalnızca doğrulama için sunucu tarafına gönderilecek verileri toplamak amacıyla formu doğrulamak için asla kullanılmaması gerektiğini unutmayın. Bu tür zayıf ve toplu olarak atanmış kodların kullanılması XSS vb.


3

Son zamanlarda aynı sorunu vardı ve bir form aynı yapıya sahip bir JSON nesnesine dönüştüren bu .toJSON jQuery eklentisi ile çıktı . Bu ayrıca, kullanıcınızın belirli yerlere daha fazla alan eklemesine izin vermek istediğiniz dinamik olarak oluşturulmuş formlar için özellikle kullanışlıdır.

Eğer bir temsil için bu formu tahmin edebilirsiniz: nokta aslında bir yapıya kendisi olduğunu, bu yüzden kullanıcı şehirdeki en sevdiği yerleri ekler nerede bir form yapmak istiyorum diyelim böylece bir form inşa etmek isteyebilirsiniz olan <places>...</places>XML öğesi içeren a kullanıcının beğendiği yerlerin listesi böylece <place>...</place>her biri örneğin bir <name>...</name>öğe, bir <type>...</type>öğe ve ardından <activity>...</activity>böyle bir yerde gerçekleştirebileceğiniz etkinlikleri temsil eden bir öğe listesi içeren bir öğe listesi . XML yapınız şöyle olur:

<places>

    <place>

        <name>Home</name>
        <type>dwelling</type>

        <activity>sleep</activity>
        <activity>eat</activity>
        <activity>watch TV</activity>

    </place>

    <place>...</place>

    <place>...</place>

</places>

Bu tam yapıyı temsil edecek bir JSON nesnesinin bunun dışında olması ne kadar güzel olurdu, böylece aşağıdakilerden birini yapabilirsiniz:

  • Bu nesneyi herhangi bir CouchDB benzeri veritabanında olduğu gibi depolayın
  • $ _POST [] sunucu tarafından okuyun ve semantik olarak değiştirebileceğiniz doğru şekilde iç içe diziyi yeniden deneyin
  • İyi biçimlendirilmiş bir XML dosyasına dönüştürmek için sunucu tarafı bir komut dosyası kullanın (a-priori'nin tam yapısını bilmeseniz bile)
  • Herhangi bir şekilde Node.js benzeri bir sunucu komut dosyasında olduğu gibi kullanın

Tamam, şimdi bir formun bir XML dosyasını nasıl temsil edebileceğini düşünmemiz gerekiyor.

Tabii ki <form>etiket root, ama sonra <place>bir veri elemanı değil, bir kap olan o elemente sahibiz , bu yüzden bunun için bir giriş etiketi kullanamayız.

İşte burada <fieldset>etiket kullanışlı geliyor! <fieldset>Etiketleri, form / XML temsilimizdeki tüm kapsayıcı öğelerini temsil etmek için kullanacağız ve böylece şöyle bir sonuç elde edeceğiz:

<form name="places">

    <fieldset name="place">

        <input type="text" name="name"/>
        <select name="type">
            <option value="dwelling">Dwelling</option>
            <option value="restoration">Restoration</option>
            <option value="sport">Sport</option>
            <option value="administrative">Administrative</option>
        </select>

        <input type="text" name="activity"/>
        <input type="text" name="activity"/>
        <input type="text" name="activity"/>

    </fieldset>

</form>

Bu formda görebileceğiniz gibi, benzersiz adlar kuralını ihlal ediyoruz, ancak bu tamam, çünkü bir dizi öğeye dönüştürülecekler, böylece sadece dizi içindeki dizinleri tarafından referans verilecekler.

Bu noktada name="array[]"formun içinde nasıl bir isim olmadığını ve her şeyin güzel, basit ve anlamsal olduğunu görebilirsiniz.

Şimdi bu formun aşağıdaki gibi görünecek bir JSON nesnesine dönüştürülmesini istiyoruz:

{'places':{

    'place':[

        {

            'name': 'Home',
            'type': 'dwelling',

            'activity':[

                 'sleep',
                 'eat',
                 'watch TV'

            ]

        },

        {...},

        {...}

    ]

}}

Bunu yapmak için burada birisi bu Kod İnceleme iş parçacığında optimize yardımcı ve bu gibi görünüyor bu jQuery eklentisi geliştirdik :

$.fn.toJSO = function () {
    var obj = {},
        $kids = $(this).children('[name]');
    if (!$kids.length) {
        return $(this).val();
    }
    $kids.each(function () {
        var $el = $(this),
            name = $el.attr('name');
        if ($el.siblings("[name=" + name + "]").length) {
            if (!/radio|checkbox/i.test($el.attr('type')) || $el.prop('checked')) {
                obj[name] = obj[name] || [];
                obj[name].push($el.toJSO());
            }
        } else {
            obj[name] = $el.toJSO();
        }
    });
    return obj;
};

Bunu daha fazla açıklamak için bu bir blog gönderisini de yaptım .

Bu, bir formdaki her şeyi JSON'a (hatta radyo ve onay kutuları) dönüştürür ve tek yapmanız gereken aramak

$.post('script.php',('form').toJSO(), ...);

Formları JSON nesnelerine dönüştürmenin birçok yolu olduğunu biliyorum .serialize()ve .serializeArray()çoğu durumda harika ve harika çalışıyorlar ve çoğunlukla kullanılmayı amaçlıyorlar, ancak bir formu anlamlı isimlerle XML yapısı olarak yazma ve iyi oluşturulmuş JSON nesnesi denemeye değer, aynı zamanda dinamik olarak oluşturulmuş form verilerini yeniden kurtarmanız gerekiyorsa endişe duymadan aynı ad giriş etiketlerini ekleyebilmeniz çok yararlıdır.

Umarım bu birine yardımcı olur!


ne yapmaya çalışıyorsun?
Onheiron


3

Başka bir cevap

document.addEventListener("DOMContentLoaded", function() {
  setInterval(function() {
    var form = document.getElementById('form') || document.querySelector('form[name="userprofile"]');
    var json = Array.from(new FormData(form)).map(function(e,i) {this[e[0]]=e[1]; return this;}.bind({}))[0];
    
    console.log(json)
    document.querySelector('#asJSON').value = JSON.stringify(json);
  }, 1000);
})
<form name="userprofile" id="form">
  <p>Name <input type="text" name="firstname" value="John"/></p>
  <p>Family name <input name="lastname" value="Smith"/></p>
  <p>Work <input name="employment[name]" value="inc, Inc."/></p>
  <p>Works since <input name="employment[since]" value="2017" /></p>
  <p>Photo <input type="file" /></p>
  <p>Send <input type="submit" /></p>
</form>

JSON: <textarea id="asJSON"></textarea>

FormData: https://developer.mozilla.org/en-US/docs/Web/API/FormData


3

[GÜNCELLEME 2020]

Vanilya JS'de basit bir oneliner ile:

Object.fromEntries(new FormData(form))

2

Samuel versiyonunu seviyorum, ama sanırım küçük bir hatası var. Normalde JSON şu şekilde gönderilir:

{ "CoreSKU": "PCGUYJS", "name_de": "ne olursa olsun", ...

Olarak DEĞİL

[{ "CoreSKU": "PCGUYJS"}, { "name_de": "ne olursa olsun"}, ...

bu nedenle IMO işlevi şunları okumalıdır:

App.toJson = function( selector ) {
    var o = {};
    $.map( $( selector ), function( n,i )
    {
        o[n.name] = $(n).val();
    });     
    return o;
}

ve veri dizisine sarmak için (yaygın olarak beklendiği gibi) ve son olarak da düzelmek App.stringify ({data: App.toJson ('#cropform: input')})

En stringify görünüm için Soru 3593046 de yağsız versiyonu için, json2.js her-sonucusun kaplı versiyonu için. Hepsini kapsamalı :)


Teşekkür ederim .. Bu (dediğin gibi) küçük ama çok önemli bir fark yaratıyor.
Adarsha

2

Hızlı ve modern bir çözüm için JSONify jQuery eklentisini kullanın . Aşağıdaki örnek GitHub README'den kelimesi kelimesine alınmıştır. Eklenti yazarı Kushal Pandya'ya tüm kredi.

Verilen:

<form id="myform">
    <label>Name:</label>
    <input type="text" name="name"/>
    <label>Email</label>
    <input type="text" name="email"/>
    <label>Password</label>
    <input type="password" name="password"/>
</form>

Koşu:

$('#myform').jsonify();

üretir:

{"name":"Joe User","email":"joe@example.com","password":"mypass"}

Bu JSON nesnesiyle bir jQuery POST yapmak istiyorsanız:

$('#mybutton').click(function() {
    $.post('/api/user', JSON.stringify($('#myform').jsonify()));
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.