首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

jQuery AJAX 傳遞陣列參數至後端完整指南:從物件序列化到 JSON 反序列化的端到端實現

     編輯:更多程式設計知識

前端傳遞陣列(特別是物件陣列)至後端是常見需求,但 $.ajax/$.post 預設序列化行為與後端接收機制存在差異。本文系統梳理傳輸格式、後端接收、JSON 反序列化全鏈路實現。

一、核心問題:物件陣列傳輸失效

// 錯誤示範:直接傳遞物件陣列
var arr = [{id:1, name:'A'}, {id:2, name:'B'}];
$.post("/api/save", { data: arr });
// 後端接收到:data[0] = "[object Object]" (字串),非結構化資料
根因:jQuery 內部呼叫 .toString() 將物件轉為 "[object Object]",後端 request.getParameterValues() 僅能接收 String[]。

二、解決方案:JSON 字串化傳輸

前端:手動構建 JSON 字串陣列

var jsonArray = [];
for (var i = 0; i < 5; i++) {
    // 手動拼接 JSON 字串(或使用 JSON.stringify)
    var item = '{"k":' + i + ',"v":' + i + '}';
    jsonArray.push(item);
}

// 發送請求:參數名建議加 [] 後綴,符合後端慣例
$.post("servlet/AjaxServlet?m=putWarningRule", { "aa[]": jsonArray });

前端最佳實踐:使用 JSON.stringify

var objects = [
    { id: 1, name: "Item 1", tags: ["tag1", "tag2"] },
    { id: 2, name: "Item 2", tags: ["tag3"] }
];

// 發送單一 JSON 字串(推薦)
$.ajax({
    url: "/api/batchSave",
    type: "POST",
    contentType: "application/json",  // 關鍵:告知後端請求體為 JSON
    data: JSON.stringify({ items: objects }),
    success: function(resp) { console.log(resp); }
});

三、後端接收實現

方案 A:傳統 Servlet 接收陣列參數(application/x-www-form-urlencoded)

@WebServlet("/servlet/AjaxServlet")
public class AjaxServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        // 關鍵:參數名需與前端一致,含 []
        String[] jsonArr = req.getParameterValues("aa[]");
        
        if (jsonArr != null) {
            for (String json : jsonArr) {
                Person p = JSONUtils.jsonToObject(json, Person.class);
                // 業務處理...
            }
        }
    }
}

方案 B:Spring MVC 接收 JSON 請求體(推薦現代專案)

@RestController
@RequestMapping("/api")
public class BatchController {
    
    @PostMapping("/batchSave")
    public ResponseEntity<String> batchSave(@RequestBody BatchRequest request) {
        List<Person> items = request.getItems();
        // 直接獲得 List,無需手動解析
        return ResponseEntity.ok("Saved " + items.size() + " items");
    }
    
    // DTO 定義
    public static class BatchRequest {
        private List<Person> items;
        // getter/setter
    }
}

四、JSON 工具類實現(基於 jsontools-core)

public class JSONUtils {
    
    /** 物件轉 JSON 字串 */
    public static String toJSONAsString(Object obj) {
        try {
            return JSONMapper.toJSON(obj).render(false);
        } catch (MapperException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /** JSON 字串轉物件(泛型) */
    @SuppressWarnings("unchecked")
    public static <T> T jsonToObject(String jsonStr, Class<T> targetClass) 
            throws TokenStreamException, RecognitionException, MapperException {
        JSONValue jv = new JSONParser(new StringReader(jsonStr)).nextValue();
        return (T) JSONMapper.toJava(jv, targetClass);
    }
    
    // 測試
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        p.setK("a"); p.setV("v");
        String json = toJSONAsString(p);
        Person np = jsonToObject(json, Person.class);
        System.out.println(np.getK() + "==" + np.getV());
    }
}

依賴座標

<dependency>
    <groupId>com.metaparadigm</groupId>
    <artifactId>jsontools-core</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>antlr</groupId>
    <artifactId>antlr</artifactId>
    <version>2.7.7</version>
</dependency>

五、複雜物件圖傳輸策略

巢狀物件(如 Person.address)同樣適用,JSON 字串完整保留結構:

// 前端
var person = {
    username: "john",
    password: "123",
    address: { city: "Taipei", zip: "100" }
};
$.ajax({
    url: "/api/savePerson",
    type: "POST",
    contentType: "application/json",
    data: JSON.stringify(person)
});

// 後端 DTO
public class Person {
    private String username;
    private String password;
    private Address address;  // 內嵌物件
    // getters/setters
}

public class Address {
    private String city;
    private String zip;
    // getters/setters
}

六、調試技巧:檢視實際傳輸參數

// Servlet 中列印所有參數名稱
Enumeration<String> names = request.getParameterNames();
while (names.hasMoreElements()) {
    String name = names.nextElement();
    System.out.println("Param: " + name + " = " + Arrays.toString(request.getParameterValues(name)));
}
// 輸出範例:Param: aa[] = ["{\"k\":0,\"v\":0}", "{\"k\":1,\"v\":1}", ...]

七、方案對比總結

方案前端 Content-Type後端接收方式適用場景優點缺點
表單陣列application/x-www-form-urlencodedrequest.getParameterValues("aa[]")簡單陣列、舊專案相容性好需手動 JSON 序列化/反序列化
JSON 請求體application/json@RequestBody DTO / JSON.parse現代 REST API、複雜物件型別安全、自動綁定、支援巢狀需 Spring/Jackson 或手動解析
FormDatamultipart/form-datarequest.getPart / @RequestPart檔案上傳混合資料支援二進制檔案處理較複雜
最佳實踐建議:
1. 新專案統一使用 JSON 請求體 + @RequestBody,前端 JSON.stringify,後端 Jackson 自動綁定。
2. 避免手動拼接 JSON 字串,防止 XSS/注入與語法錯誤。
3. 統一日期格式(ISO 8601:yyyy-MM-dd'T'HH:mm:ss.SSSZ)。
4. 定義明確的 DTO 類別,拒絕 Map<String, Object> 模糊類型。
5. 開啟 Jackson FAIL_ON_UNKNOWN_PROPERTIES=false 兼容版本演進。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved