サイトアイコン たくましゅくじょ

AjaxでJavaのFormクラスのList型変数にデータを送る方法

URLやAjaxで画面の変更ををサーバに送信する際、dataに配列形式のパラメータを追加してJavaのFormクラスでList型として受け取る方法を紹介します。
画面のテーブルにリストを表示し、データを編集した際などに利用したかったのですが方法がわからず、Google検索では上位に表示されずとても困りました。
あまり利用されていないのでしょうか。

一番下で実装例で紹介しているソースコードの、Ajaxの送信や画面の要素の取得にはjQueryを利用しています。

やりたいこと

例えば画面から配列構造のパラメータを送り、以下のような構造のFormクラスでList型のデータとして受け取りたい場合についてです。

/** 管理番号 */
public int controlNo;

/** ユーザリスト */
public List<UserInfoListDto> userInfoList; // ←これをパラメータから受け取りたい
/** ユーザID */
public String userId;

/** 氏名 */
public String name;

まず、URLを直接たたく場合(URLのクエリに指定する場合や試験など)では以下の形式で送信します。

~~/update?controlNo=1&userInfoList[0].userId=U001&userInfoList[0].name=太郎&userInfoList[1].userId=U002&userInfoList[1].name=花子

Ajaxの場合、以下の連想配列のオブジェクトをAjaxのdataとして指定することで、目的を達成することができます。


var sendList = {
    "controlNo": 1, 
    "userInfoList[0].userId": "U001", 
    "userInfoList[0].name": "太郎", 
    "userInfoList[1].userId": "U002", 
    "userInfoList[1].name": "花子"
}

ポイントは、配列のkeyが”userInfoList[0].userId”のように全て文字列となっていることです。
リストということで、userInfoListの多次元配列にするのではないということに注意してください。

JavaScliptの実装

デーブルからデータを取得し、Ajaxで送る実装例です。
上に記したFormクラスの例に対応しています。
※サンプルのためHTMLは極力シンプルにしていますが、実際はtdタグの中にinputタグやselectタグなんかを置き、内容を編集したりして使うと思います。

ユーザID 氏名
U001 太郎
U002 花子

<label>管理番号:<input type="number" id="controlNo" value="1"></label>

<table id="userInfoTable"> <thead> <tr> <th>ID</th> <th>氏名</th> </tr> </thead> <tbody> <tr> <td class="userId">U001</td> <td class="name">太郎</td> </tr> <tr> <td class="userId">U002</td> <td class="name">花子</td> </tr> </tbody> </table>
<button id="submitButton">送信</button>

$("#submitButton").on("click", function(){

    // サーバに送る連想配列
    var sendList = {};
    sendList["controlNo"] = $("#controlNo").val();

    // ループ処理でテーブルからデータを取得し、sendListに格納
    var tableData = $("#userInfoTable tbody tr");
    tableData.each(function(i){
        var $elm = $(this);
        sendList["userInfoList[" + i + "].userId"] = $elm.find(".userId").text();
        sendList["userInfoList[" + i + "].name"] = $elm.find(".name").text();
    });

    // Ajax通信でデータをサーバに送信する
    $.ajax({
        type : "POST",
        url : "/update",
        dataType : "json",
        data : sendList,
        timeout: 10000
    }).done(function(resultData) {
        // Ajax通信成功時の処理
    }).fail(function(jqXHR, textStatus, errorThrown){
        // Ajax通信失敗時の処理
    });
});

事前知識として持っていない場合、ちょっと特殊のためトライ&エラーでたどり着くことのできない解ですよね。
自分でも時々忘れてしまうので、備忘録もかねてこうして記しておこうと思います。

[追記]
Spring Boot の Controller でメソッドに @RequestBody がついている場合はこれでは送れませんでした。
どうやらクライアントからContent-Typeをapplication/jsonでリクエストする際は、データの組み立て部分を以下のようにするようです。


    // サーバに送る連想配列
    var sendList = {};
    var sendObj = [];

    sendList["controlNo"] = $("#controlNo").val();

    // ループ処理でテーブルからデータを取得し、sendListに格納
    var tableData = $('#userInfoTable tbody tr');
    tableData.each(function(i){
        var $elm = $(elm);

        var userId = $elm.find(".userId").text();
        var name = $elm.find(".userId").text();

        var tableObj = {"userId" : userId, "name" : name};
        sendObj.push(tableObj);
    });

    sendList["userInfoList"] = sendObj;

    console.log(sendList);
    // ↑ {controlNo: "1", userInfoList: Array(2)}

    console.log(sendList.userInfoList);
    // ↑ [{userId: "U001", name: "太郎"}, {userId: "U002", name: "花子"}]


モバイルバージョンを終了