首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

JSON 數據交互最佳實踐:Map 封裝解決 JSONObject 轉義難題

     編輯:Java 綜合教學

Spring MVC 返回 JSON:用 Map 統一響應結構,徹底告別反斜杠轉義

在基於 Spring MVC 的項目中,直接將對象/集合序列化為 JSON 字符串再放入響應對象,常導致雙重序列化產生 \\ 轉義字符。本文提供「Map 封裝 + JSONArray 顯式轉換」標準模式,確保輸出純淨 JSON,並給出完整 Controller 實現代碼。

一、問題根因

// 錯誤示範
String json = JSONObject.fromObject(userList).toString(); // 產生 "[{\"name\":\"A\"}]"
returnMsg.setMsg(json); // 再次序列化 → "{\"msg\":\"[{\\\"name\\\":\\\"A\\\"}]\"}"

雙層 toString() 導致反斜杠轉義,前端需 JSON.parse 兩次,極易出錯。

二、標準解決方案:Map + JSONArray

@RequestMapping("/dept/users")
public void deptUsers(HttpServletResponse response, @RequestParam Long deptId) throws IOException {
    List<User> userList = accountManager.findDeptUser(deptId);

    // 1. 配置 JsonConfig:排除循環引用、忽略字段
    JsonConfig jsonConfig = new JsonConfig();
    jsonConfig.setExcludes(new String[]{"role"});
    jsonConfig.setIgnoreDefaultExcludes(true);
    jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);

    // 2. 顯式轉為 JSONArray(非字符串)
    JSONArray jsonArray = JSONArray.fromObject(userList, jsonConfig);

    // 3. 構建響應 Map
    Map<String, Object> resultMap = new HashMap<>();
    resultMap.put("success", true);
    resultMap.put("msg", jsonArray); // 直接放 JSONArray 對象
    resultMap.put("errmsg", "");

    // 4. 統一輸出:再次用 JSONArray.fromObject(Map) 確保頂層也是標準 JSON
    response.setHeader("Cache-Control", "no-cache");
    response.setContentType("application/json; charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
    try (PrintWriter out = response.getWriter()) {
        out.print(JSONArray.fromObject(resultMap).toString());
        out.flush();
    }
}

三、關鍵點解析

  1. JsonConfig:setExcludes 過濾敏感/循環字段;LENIENT 策略遇到循環引用輸出 null 而非拋異常。
  2. JSONArray.fromObject(Collection):直接生成 JSON 數組對象,而非字符串,避免首層轉義。
  3. Map 作為頂層容器:靈活組裝 success、msg、errmsg、data 等字段,最終統一 JSONArray.fromObject(map) 序列化一次,保證輸出合法 JSON 對象 {...}。
  4. 響應頭設置:application/json + UTF-8,防止中文亂碼;no-cache 避免瀏覽器緩存舊數據。

四、現代替代方案:Jackson + @RestController

若專案已引入 Spring Boot / Jackson,強烈建議遷移:

@RestController
@RequestMapping("/api/dept")
public class DeptController {
    @GetMapping("/{deptId}/users")
    public Result<List<UserDTO>> deptUsers(@PathVariable Long deptId) {
        List<User> users = accountManager.findDeptUser(deptId);
        List<UserDTO> dtos = users.stream().map(this::convert).collect(toList());
        return Result.success(dtos);
    }
}

// 統一響應封裝
@Data
class Result<T> {
    private boolean success;
    private T data;
    private String errmsg;
    public static <T> Result<T> success(T data) {
        Result<T> r = new Result<>(); r.setSuccess(true); r.setData(data); return r;
    }
}
  • 自動序列化、內容協商、異常處理一體化。
  • @JsonIgnore、@JsonView 精細控制字段輸出。
  • 無需手動操作 HttpServletResponse,代碼量減少 80%。

五、總結

舊項目維護期:用 Map + JSONArray 模式快速修復轉義問題;新項目/重構期:全面擁抱 Spring Boot + Jackson + @RestController,享受聲明式 JSON 開發體驗。核心原則:對象進、對象出,框架負責序列化,業務碼零觸碰 JSON 字符串。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved