jQueryを使用してフォームデータをJavaScriptオブジェクトに変換する


1624

フォームのすべての要素をJavaScriptオブジェクトに変換するにはどうすればよいですか?

各要素をループすることなく、フォームからJavaScriptオブジェクトを自動的に構築する方法が欲しいのですが。によって返される文字列は必要ありません。また、によって$('#formid').serialize();返されるマップも必要ありません。$('#formid').serializeArray();


16
1つ目は、GETメソッドを使用してフォームを送信した場合とまったく同じように文字列を返し、2つ目は名前と値のペアを持つオブジェクトの配列を提供するためです。「email」という名前のフィールドがある場合、obj.emailでその値を取得できるようにするオブジェクトを取得します。serializeArray()を使用すると、obj [indexOfElement] .valueのようなものを実行する必要があります
Yisroel

2
@James-D. CrockfordのJSON-jsライブラリを使用して受け入れられた回答。ここでは例があります:github.com/tleese22/google-app-engine-jappstart/blob/master/src/...
テイラーLeese

4
@テイラーはい、正しい答えはCrockfordのlibとTobiasの関数を次のように使用していると思います:JSON.stringify($( 'myForm')。serializeObject())
James McCormack

5
@Jonz-送信/送信以外にも、フォーム要素を使用する理由があります。JavaScript内でフォームの値(たとえば、単一ページアプリ)を大幅に引き上げる場合は、アクセスと操作のためにオブジェクト形式にするのが非常に便利です。また、データを移動するための形式は、HTTP PostおよびGetクエリ文字列だけではありません。
Patrick M

3
私は>>出くわし良いJS github.com/marioizquierdo/jquery.serializeJSON
Bongs

回答:


1657

serializeArrayすでに正確にそれを行います。データを必要な形式にマッサージするだけです。

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;
}

上書きされるため、実際の入力と同じ名前の非表示フィールドに注意してください。


4
tvanfossonが言うように、なぜコレクションを2回繰り返すのですか?
イスロエル

69
「serializeArrayを使用して最初にデータを取得する理由」という意味ですか?serializeArrayはすでに記述されているため、複数のブラウザーで単体テストされており、理論的には、jQueryの今後のバージョンで改善される可能性があります。DOM要素などの一貫性のないものに直接アクセスする必要のあるコードを少なくするほど、コードはより安定します。
トビアスコーエン

56
注意してください、serializeArray()は無効化された要素を含みません。ページの他の要素と同期されている入力要素を無効にすることがよくありますが、それでもシリアル化されたオブジェクトにそれらを含めたいです。$.map( $("#container :input"), function(n, i) { /* n.name and $(n).val() */ } );無効化された要素を含める必要がある場合などに使用した方がよいでしょう。
Samuel Meacham

22
@TobiasCohen foo[bar]他のほとんどの入力名の種類については言うまでもなく、-type入力は期待どおりに処理されません。この問題に対する浅い解決策に非常にイライラした後、私は自分のjQueryプラグインを作成することになりました。
マセック

6
@macek私はこれが数か月前のものであることを知っていますが、いつから配列は数値以外のインデックスを使用したのですか?だれも入力foo [bar]に名前を付けて、それを配列として扱うことを望んではなりません。配列とハッシュを混同していますか?はい、[]は一般にアクセサーであると理解されていますが、配列だけではありません。また、これは有効なHTMLであるがHTML仕様にはないというのは矛盾です。はい、ブラウザはそれでチョークしないかもしれませんが、多くのウェブサーバーは配列のようにそれを逆シリアル化する方法を知っているでしょう。どうして?それはHTML仕様にはないからです。したがって、それは確かに無効です。
kroehre 2012

446

上司のようにフォームをJSONに変換する


現在のソースはGitHubBowerにあります。

$ bower install jquery-serialize-object


次のコードは廃止されました

次のコードは、あらゆる種類の入力名を処理できます。期待どおりに処理します。

例えば:

<!-- 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"
          }
        }
      }
    }
  }
}

使用法

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

ソーサリー(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
それで、それはかなりうまくいきます。しかし、その名前は間違っています。名前が示すように、JSONを返しません。代わりに、オブジェクトリテラルを返します。{番号:[ "1"、 "3"、のindexOf:機能(){...}]}また、そうでない場合は、あなたの配列は次のように、彼らのプロトタイプに添付だ何かを持って、hasOwnPropertyをチェックするために重要です
frontendbeauty

5
@frontendbeauty実際には、toJSONは仕様が言うべきものとまったく同じです:developer.mozilla.org/en/JSON#toJSON() _method 残念な誤解
ライアンフローレンス

4
@Marek、私はjsfiddleでここでテストを行いました。コツはあなたの選択に適切に名前を付けることです。<select name="foo" multiple="multiple">どのシナリオでも機能しません。あなたが使用している場合しかし、[]、のように<select name="bar[]" multiple="multiple">、それはうまく動作します:)
マセック

3
github.com/serbanghita/formToObjectは同様のJavaScriptメソッド(サードパーティのライブラリは不要)であり、同じ働きをすることを指摘したかったのです。「複数」をサポートし、「無効」な要素を無視します。
Șerban Ghiță 2013

8
このソリューションは、フォーム要素名としてネストされたキーの問題を処理するため、最上位にする必要があります。
SquareCat 2014

283

どうしたの:

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

2
@LayZee-何も選択されていない場合、なぜそれをバックエンドにしたいですか?オプションを選択する必要がある場合は、シリアル化する前に入力を検証してください。
2014

21
何も返さない場合は、.each代わりに単に使用しないのです.mapか?
azerafati 2014年

10
それはとても素朴なので、とてもシンプルです...同じ名前のチェックボックスを扱いません。毎回、その前のチェックされた項目をオーバーライドします。正しくシリアル化されるようにするには、入力タイプの検出が必要です。
Joshua F. Rountree、2015

5
純粋なjQueryソリューションが必要な場合は、次を使用できますvar 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;}, {})
サイト

103

Tobias Cohenのソリューションの修正バージョン。これは0およびのような偽の値を正しく処理します''

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;
};

そして、コーディングの便宜のためのCoffeeScriptバージョン:

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

value = @value ? ''
コーヒースクリプト

また、Railsのようなフォームをシリアル化しようとしている場合は、生成されたキーから要素ルートを削除することをお勧めします。これを実現するために、新しいパラメーターkeyMapと次の行を追加しましたkey = if keyMap? then keyMap(@name) else @name。これで、のようなマッピング関数を渡すことができます(name) -> name.match(/\[([^\]]+)]/)[1]。そしてもちろん、その後@nameにすべてを変更する必要がありますkey
DamirZekić

@DamirZekić、ルート要素がpostだった場合は、簡単にできます$('form').serializeObject().post。派手なマッピングの必要はありません。
マセック

@DamirZekićこの行は何をしていますか?if (!objectData[this.name].push)??
kittu 2017年

@kittuこれobjectData[this.name]は、pushメソッドがあるかどうかをチェックしています(大まかに言って、配列かどうか)。配列の場合は値をプッシュし、配列でない場合は配列に変換して、同じキーを持つ複数の値が配列に結合されるようにします。
Daniel X Moore

63

Array.prototype.reduceワンライナーであり、Underscore.jsなどに依存しないため、私は使用するのが好きです。

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

これはを使用した回答に似てArray.prototype.mapいますが、追加のオブジェクト変数でスコープを混乱させる必要はありません。ワンストップショッピング。

重要な注意:入力が重複するname属性を持つフォームは有効なHTMLであり、実際には一般的なアプローチです。この場合、このスレッドで回答を使用することは不適切です(オブジェクトキーは一意である必要があるため)。


これはとてもエレガントです。ただしarray.prototype.reduce()、これはECMAScript 5仕様の一部であるため、IE8では使用できないことに注意してください。したがって、IE8のサポートが必要な場合は、ポリフィルまたは別のソリューションを完全に使用する必要があります。
gfullam 2015

3
確かに、ポリフィルするのは簡単です。また、IE11エンタープライズモードでのMicrosoftのすばらしい仕事のおかげで、IE8の頭痛はほぼ終わりました-IE8を使用する個々のユーザーには対応できなくなりましたが、10,000人の従業員がすべてIE8を使用する組織が登場すると、それは異なります。幸い、マイクロソフトはその問題に懸命に取り組んでいます。
Ethan Brown

1
まあ、IT担当者にIE11 Enterpriseモードを調べてもらう必要があります。これは、最新のブラウザーとIE8互換アプリを実行する方法を提供します。Microsoftの一部のスマート移動:howtogeek.com/184634/...
イーサン・ブラウン

30

これらの答えはすべて、私にはとても上にあるように見えました。簡単にするために言うべきことがあります。すべてのフォーム入力にname属性が設定されている限り、これは単にjim dandyで機能するはずです。

$('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
ただし、ネストされたフォームデータは処理しません。そのため、回答はより複雑になります。
frontendbeauty 2011

私にとってはうまくいきました。キーと値のペアのストレージが必要です。文字列化してからlocalStorageまたはcookieに保存しても、うまくいきませんでした。
Greg Pettit 2013年

23

実際にこれを行うには、各要素を調べる必要があります。あなたが本当に知りたいことは、「フォームをJSONオブジェクトに変換するメソッドを他の誰かがすでに書いているのですか?」です。次のようなものが機能するはずです-POST経由で返されるフォーム要素のみを提供することに注意してください(名前が必要です)。これはテストされていません

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;
}

確かに、私のためにこれを行うプラグインが大好きです。名前を持つことの制限は大したことではありません。これは、textareasやselectsを含むフォームのすべてのフィールドをプルしますか?
イスロエル

[無効]を考慮したいかどうかはわかりませんが、送信/ピックアップする必要があるとは思いません。
meder omuraliev 2009

serializeArray()を使用してマップを取得し、上記と同様のコードを使用して通常のJSONオブジェクトに変換する方が簡単かもしれません。この方法では、フォーム自体を処理しません
Yisroel

2
serializedArrayを使用しても機能しますが、基本的にはコレクションを2回繰り返します。1回は配列を生成し、次に配列を繰り返します。その必要性はわかりません。
tvanfosson 2009

セレクターを有効/無効に調整します。
tvanfosson 2009

23

使用している場合はUnderscore.jsを、あなたは比較的簡潔な使用することができます。

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

19

他のすべての回答に問題があることを確認しました。入力名がなどの配列の場合、次のようname[key]に生成されるはずです。

name:{ key : value }


例:次のようなHTMLフォームがある場合:

<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>

しかし、それは以下のJSONのように生成されるべきであり、他のすべての答えで次のようなオブジェクトにはなりません。したがって、誰かが次のJSONのようなものを持ち込みたい場合は、以下のJSコードを試してください。

{
    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>


この回答は言及されたケースをカバーしますが、checkbox []やone [another] [another_one]のようなケースはカバーしません
Leonardo Beal

1
@LeonardoBeal私は私のansを修正しました..これを今チェックしてください..!
Bhavik Hirani 2018

私は反対投票者であり、私は反対投票してevalいます。このようevalに使用すると、非常に信頼性が低く、バグが多く、パフォーマンスが低下し、安全でない可能性があるため、この方法で使用すべきではありません。
ジャック

2
これは良い答えだとは思えません。そして、答えを書くときは、コードを自明にするか説明してください。this.c = function(k,v){ eval("c = typeof "+k+";"); if(c == 'undefined') _t.b(k,v);}短いが説明的ではない。経験の少ない開発者は、なぜ、どのように機能するかを理解せずに、これをコピーします。
iRaS

2
@JackGiffinコードeval()から削除したので、今すぐ新しいコードを確認してください。
Bhavik Hirani

17

わかりました、これはすでに非常に賛成された回答であることを知っていますが、別の同様の質問が最近尋ねられ、私もこの質問に向けられました。私のソリューションも提供したいと思います。これは、受け入れられたソリューションよりも優れているためです。無効にしたフォーム要素を含めることができます(UIの機能によっては、重要になる場合があります)。

ここに他のSO質問からの私の答えがあります

最初はjQueryのserializeArray()メソッドを使用していましたが、無効になっているフォーム要素は含まれていません。多くの場合、ページ上の他のソースと「同期」されているフォーム要素を無効にしますが、シリアル化されたオブジェクトにデータを含める必要があります。そうserializeArray()です。:inputセレクターを使用して、特定のコンテナー内のすべての入力要素(有効と無効の両方)を取得$.map()し、オブジェクトを作成しました。

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

これが機能するためには、各入力にname属性が必要であることに注意してください。これは、結果のオブジェクトのプロパティの名前になります。

これは実際に使用したものから少し変更されています。.NET IDictionaryとして構造化されたオブジェクトを作成する必要があったので、これを使用しました(有用な場合に備えて、ここで提供します)。

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

これらのソリューションはどちらも好きです。なぜなら、これらは$.map()関数の単純な使用法であり、セレクターを完全に制御できるからです(結果として、結果のオブジェクトにどの要素が含まれるか)。また、追加のプラグインは必要ありません。プレーンな古いjQuery。


6
私はこれをプロジェクトで試しました、mapこれを使用して単一のプロパティを持つオブジェクトの配列を作成します、それはプロパティをすべて1つのオブジェクトに集約しません。
joshperry

16

この関数は、同じ名前の複数の要素とともに多次元配列を処理する必要があります。

私はこれまで数年間使用してきました:

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

あなたはこれを行うことができます:

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

JSONを参照してください。


14

ワンライナー(jQuery以外の依存関係なし)は、mapメソッドに渡される関数に固定オブジェクトバインディングを使用します。

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

それは何ですか?

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

プログレッシブWebアプリに適しています(通常のフォーム送信アクションとajaxリクエストの両方を簡単にサポートできます)


12

使用する:

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;
}

出力:

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

7

シンプルさはここが一番です。私は単純な文字列を正規表現に置き換えて使用しましたが、これまでのところ魅力的なものでした。私は正規表現の専門家ではありませんが、非常に複雑なオブジェクトを入力することもできます。

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

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

7

いくつかの古い答えから:

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

私が言えることとの違いは、あなたのソリューションは依存しないので、serializeArray好きな入力を自由に選択できることです(たとえば、無効な入力を含めることができます)。つまり、これはどのフォームや送信イベントとも結び付けられていません。それ自体が独立していますか?
dvtan 2016年

リンクされた回答との唯一の小さな違いは、インスタンス化に必要なデータがなくreduce、オブジェクトを返すことです。toArrayjQuery からのものであるため、これは独立したものではありません。
サイト

6

Tobias Cohenのコードに問題があることを発見しました(直接コメントするための十分なポイントがありません)。同じ名前の2つの選択オプションがあり、どちらもvalue = ""の場合、元のコードは "name":[""、 ""]ではなく "name": ""を生成します。

これは、最初のif条件に「|| o [this.name] == ''」を追加することで修正できると思います。

$.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のソリューションを使用して、ASP.NET MVCが同じフォーム上のネストされた/複雑なオブジェクトを処理する方法で動作するように修正しました。あなたがしなければならないすべてはこれに検証部分を修正することです:

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

これにより、次のような名前の要素が一致し、正しくマッピングされます。

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

そして

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

5

私は、この問題が見つかり最も簡単かつ正確な方法は、使用していたバーベキューのプラグインや、この1(0.5Kバイトのサイズについてです)。

多次元配列でも機能します。

$.fn.serializeObject = function()
{
	return $.deparam(this.serialize());
};


これはうまく動作するようです。bowerとnpmの記述ファイルを含むjquery-deparamの代替リポジトリがあります。
Alf Eaton



3

2つのコレクションを繰り返す必要がなく、必要に応じて「名前」と「値」以外のものを取得でき、オブジェクトに保存する前に値をサニタイズできるので、このアプローチを好みます(たとえば、保存したくないデフォルト値がある場合)。

$.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;
}

そのように使用してください:

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

Firefoxでのみテストされています。


3

何かをオブジェクトに変換します(単体テストではありません)

<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>

テストの出力:

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

オン

<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>

生成されます:

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

3

選択したソリューションに問題が見つかりました。

配列ベースの名前を持つフォームを使用すると、jQuery serializeArray()関数が実際に終了します。

複数のビューで同じフォームを同じページに複数回配置できるようにするために、配列ベースのフィールド名を使用するPHPフレームワークがあります。これは、フォームモデルが競合することなく、追加、編集、削除の両方を同じページに配置するのに便利です。

この絶対的な基本機能を削除せずにフォームをシリアライズしたかったので、独自のseralizeArray()を作成することにしました。

        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;
            }
        });

注:これはsubmit()フォーム以外でも機能するため、コードの残りの部分でエラーが発生した場合、「変更を保存」というリンクボタンをクリックしてもフォームは送信されません。

また、この関数は、検証のためにサーバー側に送信するデータを収集するためだけにフォームを検証するために使用しないでください。そのような弱くて大量に割り当てられたコードを使用すると、XSSなどが発生します。


3

最近同じ問題が発生し、フォームを同じ構造のJSONオブジェクトに変換するこの.toJSON jQueryプラグインが出てきました。これは、ユーザーが特定の場所にフィールドを追加できるようにする動的に生成されるフォームにも特に役立ちます。

重要なのは、フォーム自体を構造化してフォーム自体を構築したい場合があるため、ユーザーがお気に入りの場所を町に挿入するフォームを作成したいとします。このフォームを<places>...</places>含むXML要素を表すと想像できます。したがって、ユーザーが気に入っている場所のリスト、つまり、<place>...</place>それぞれが要素<name>...</name><type>...</type>要素、次にその<activity>...</activity>ような場所で実行できるアクティビティを表す要素のリストなどを含む要素のリスト。したがって、XML構造は次のようになります。

<places>

    <place>

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

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

    </place>

    <place>...</place>

    <place>...</place>

</places>

この中に正確な構造を表すJSONオブジェクトがあり、次のいずれかを実行できるとしたら、どれほどすばらしいでしょう。

  • このオブジェクトをCouchDBのようなデータベースにそのまま保存します
  • $ _POST []サーバー側から読み取り、意味的に操作できる正しくネストされた配列を取得します
  • サーバーサイドスクリプトを使用して、整形式のXMLファイルに変換します(正確な構造が事前にわからない場合でも)
  • Node.jsのようなサーバースクリプトでそのまま使用する

では、フォームがXMLファイルをどのように表すことができるかを考える必要があります。

もちろん<form>タグはですがroot、それから<place>データ要素自体ではなくコンテナで要素があるため、inputタグを使用できません。

ここで<fieldset>タグが役に立ちます!<fieldset>タグを使用して、すべてのコンテナー要素をフォーム/ XML表現で表すため、次のような結果が得られます。

<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>

このフォームからわかるように、一意の名前の規則を破っていますが、要素の配列に変換され、配列内のインデックスによってのみ参照されるため、これは問題ありません。

この時点でname="array[]"、フォーム内に同様の名前がないこと、そしてすべてがかなりシンプルでセマンティックであることがわかります。

次に、このフォームを次のようなJSONオブジェクトに変換します。

{'places':{

    'place':[

        {

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

            'activity':[

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

            ]

        },

        {...},

        {...}

    ]

}}

これを行うために、私はこのjQueryプラグインをここで開発しました。誰かがこのコードレビュースレッドで最適化を手助けし、次のようになります。

$.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;
};

私もこのブログ投稿をしましたについてさらに説明するために、。

これにより、フォーム内のすべてがJSON(ラジオやチェックボックスも含む)に変換され、あとは呼び出しを行うだけです

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

フォームをJSONオブジェクトに変換する方法はたくさんあり、ほとんどの場合確実.serialize().serializeArray()機能し、ほとんどの場合使用することを目的としていますが、意味のある名前のXML構造としてフォーム記述し、それを整形式のJSONオブジェクトは試してみる価値があります。動的に生成されたフォームデータを取得する必要がある場合、心配することなく同じ名前の入力タグを追加できるという事実は非常に役立ちます。

これが誰かを助けることを願っています!


あなたは何をしようとしているのですか?
Onheiron 2013

3

自分で多次元JavaScriptオブジェクトにフォームをコーディングして、本番環境で使用しました。結果はhttps://github.com/serbanghita/formToObject.jsです。


私はこれのバリエーションを非常に具体的な実装に使用しました、ありがとうございます!
クリスベイカー

お役に立ててありがとうございます。ロールする新機能がいくつかあり、これが私をやる気にさせます。
Șerban Ghiță

3

別の答え

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

[2020年更新]

バニラjsのシンプルなワンライナーで:

Object.fromEntries(new FormData(form))

2

私はサミュエルズバージョンが好きですが、小さな間違いがあると思います。通常、JSONは次のように送信されます

{"coreSKU": "PCGUYJS"、 "name_de": "何でも"、...

ではない

[{"coreSKU": "PCGUYJS"}、{"name_de": "whatever"}、...

したがって、関数IMOは次のようになります。

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

そして、それをデータ配列でラップし(一般的に予想されるように)、最後にそれをastringとして送信しますApp.stringify({data:App.toJson( '#cropform:input')})

文字列化については、無駄のないバージョンについては質問3593046を、あらゆる事象に対応するバージョンについてはjson2.js参照してください。それはそれをすべてカバーするはずです:)


ありがとうございます。これは、(ご指摘のとおり)ごくわずかですが非常に重要な違いになります。
アダルシャ

2

迅速で最新のソリューションについては、JSONify jQueryプラグインを使用してください。以下の例は、GitHubのREADMEをそのまま使用したものです。プラグインの作者であるKushal Pandyaの功績です。

与えられた:

<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>

ランニング:

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

生成する:

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

このJSONオブジェクトでjQuery POSTを実行する場合:

$('#mybutton').click(function() {
    $.post('/api/user', JSON.stringify($('#myform').jsonify()));
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.