10

jQuery を使用して $.serializeArray() によって生成される数値インデックス形式とは対照的に、HTML フォーム データを Associated Array にシリアル化するにはどうすればよいですか?

jQuery.serializeArray によって得られる出力では、数値インデックス キーを使用して値を直接選択することが難しくなります。フォーム入力でチェック ボックスを使用すると、わずかなインデックス シフトが発生する可能性があります。

serializeArray の出力

[
  0: [name: 'field-1', value: 'val1'],
  1: [name: 'check', value: 'val2'],
  2: [name: 'check', value: 'val3']
]

望ましい出力-より信頼性の高い形式とより簡単な値へのアクセス

[
  'field-1' : 'val1',
  'check' : [ 0 : 'val2', 1 : 'val3' ]
]
4

1 に答える 1

6

2021年更新

これは非常に古い問題でした。最近の JavaScript ははるかに寛容であり、元のソリューションは時代遅れになりました。JavaScript の改良により、jQuery もかなり時代遅れになりました。

この最初の投稿以来、フォント/バックエンド環境で JSON との間で配列、オブジェクト、さらにはネストされた両方の組み合わせをシリアル化するためのサポートが大幅に簡素化されました。

複雑なユーザー入力を送信するための次のオプションを見てください。

ネイティブ

JSON の操作

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON

JSON リクエスト オプションを使用したフェッチの例

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#supplying_request_options

アクシオス

fetchネイティブ ES6+ JavaScript の代替。Axios が配列とオブジェクトのシリアル化を処理します。

https://github.com/axios/axios

NodeJS

QueryString - プロジェクトでサポートされている場合、NodeJS からこのヘルパー クラスをインポートできます。

https://nodejs.org/api/querystring.html )


以下の古いコンテンツ

私にとってうまくいった解決策は、フォームの複数選択オプションからの多次元配列も処理できる独自の jQuery 関数 $.serializeAssoc() および $.serializeObject() の代替を作成することでした。

これら 2 つの機能には長所と短所があります。私は serializeAssoc を使用して、通常は JS Validation で一般的な値に直接アクセスするためにフォーム データを簡素化します。

serializeObject は、カスタム数値キー インデックスを使用する多機能フォームで便利です。複数選択フィールドの複雑なフォーム設定から送信された情報のデータ ペアリングや、フォーム内のデータが親子関係を持つ DOM によって構築された値を持つフォームを簡素化します。 serializeAssoc ではうまく処理できないものがあります。

serializeAssoc

次の関数は長さチェックを許可しますが、カスタム数値キー インデックスに問題があります。AJAX 呼び出しで配列を送信すると、インデックス パディングが発生します。

$.fn.serializeAssoc = function() {
  var data = {};
  $.each( this.serializeArray(), function( key, obj ) {
    var a = obj.name.match(/(.*?)\[(.*?)\]/);
    if(a !== null)
    {
      var subName = a[1];
      var subKey = a[2];

      if( !data[subName] ) {
        data[subName] = [ ];
      }

      if (!subKey.length) {
        subKey = data[subName].length;
      }

      if( data[subName][subKey] ) {
        if( $.isArray( data[subName][subKey] ) ) {
          data[subName][subKey].push( obj.value );
        } else {
          data[subName][subKey] = [ ];
          data[subName][subKey].push( obj.value );
        }
      } else {
        data[subName][subKey] = obj.value;
      }
    } else {
      if( data[obj.name] ) {
        if( $.isArray( data[obj.name] ) ) {
          data[obj.name].push( obj.value );
        } else {
          data[obj.name] = [ ];
          data[obj.name].push( obj.value );
        }
      } else {
        data[obj.name] = obj.value;
      }
    }
  });
  return data;
};

serializeObject

次の関数は、パディングを発生させずにカスタム数値インデックスを許可しますが、長さチェックを防ぎます。必要に応じて、each ループを使用してインデックス キーの数を確認します。オブジェクトを AJAX 呼び出しで送信する場合、最初に JSON.Stringify を使用し、値を var に渡してサーバー側でデコードする必要があります。直接使用すると、一部のブラウザーで予期しない行末エラーが発生するためです。

$.fn.serializeObject = function() {
    var data = {};
    $.each( this.serializeArray(), function( key, obj ) {
        var a = obj.name.match(/(.*?)\[(.*?)\]/);
        if(a !== null)
        {
            var subName = new String(a[1]);
            var subKey = new String(a[2]);
            if( !data[subName] ) {
              data[subName] = { };
              data[subName].length = 0;
            };
            if (!subKey.length) {
                subKey = data[subName].length;
            }
            if( data[subName][subKey] ) {
              if( $.isArray( data[subName][subKey] ) ) {
                data[subName][subKey].push( obj.value );
              } else {
                data[subName][subKey] = { };
                data[subName][subKey].push( obj.value );
              };
            } else {
                data[subName][subKey] = obj.value;
            };
            data[subName].length++;
        } else {
            var keyName = new String(obj.name);
            if( data[keyName] ) {
                if( $.isArray( data[keyName] ) ) {
                    data[keyName].push( obj.value );
                } else {
                    data[keyName] = { };
                    data[keyName].push( obj.value );
                };
            } else {
                data[keyName] = obj.value;
            };
        };
    });
    return data;
};

使用法:

機能の追加

<script>
  (function($){
    $.fn.serializeAssoc = function() {
      ... As Presented Above ...
    };
    $.fn.serializeObject = function() {
      ... As Presented Above ...
    };
  })(jQuery);
</script>

サンプルフォーム

<form id="myForm">
  <input type="text" name="myName" />

  <select name="consoles" multiple>
    <option selected>PC</option>
    <option selected>XBOX 360</option>
    <option selected>PS3</option>
  </select>

  <input type="text" name="sample[100]" value="Mario" />
  <input type="text" name="sample[101]" value="Brothers" />

  <input type="submit" name="submit" value="Submit" />
</form>

機能の使用

<script>
  (function($) {
    $('#myForm').submit(function(e){
      e.preventDefault();
      var formData = $('#myForm').serializeAssoc();
      console.log(formData);
    });
  })(jQuery);
</script>

動的フォームの例

<form id="myForm">
  <input type="text" name="myName" value="Spuggy" />

  <div id="characters">
    <input type="text" name="character[]" value="Mario" />
    <input type="text" name="character[]" value="Sonic" />
  </div>

  <div id="consoles">
    <input type="text" name="console[xbox]" value="XBOX One" />
    <input type="text" name="console[playstation]" value="PlayStation 4" />
  </div>

  <input type="submit" name="submit" value="Submit" />
</form>

<script>
  (function($) {
    $('#myForm').submit(function(e){
      e.preventDefault();
      var formData = $('#myForm').serializeAssoc();
      console.log(formData);
    });
  })(jQuery);
</script>

動的フォーム出力

[
  myName: 'Spuggy',
  character: [
    0: 'Mario',
    1: 'Sonic'
  ],
  console: [
    'xbox': 'XBOX One',
    'playstation': 'PlayStation 4'
  ]
]
于 2013-10-28T19:21:01.090 に答える