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

Spring MVC 返回 JSONObject 空值陷阱:null 值導致前端 500 錯誤與解決方案

     編輯:Java 綜合教學

現象還原

Controller 返回 JSONObject,當查詢無結果時 userId = null,前端收到 500 Internal Server Error,JS 回調不執行。

根因分析

代碼寫法userId 為 null 時結果前端表現
json.accumulate("userId", userId) 直接放 null {"userId":null} jQuery $.getJSON 解析拋錯,進入 error 回調,HTTP 500
Integer.toString(userId) 未判空 拋 NullPointerException Spring MVC 異常解析器返回 500,前端無數據
try-catch 吞掉 NPE,返回 {} {} (空對象) 前端成功回調,data.userId === undefined,邏輯正常

最佳實踐:三層防護

1. 服務層:返回 Optional / 統一響應對象

public Optional getUserId(String phone) {
    Integer id = dao.selectUserId(phone);
    return Optional.ofNullable(id);
}

2. Controller 層:構建無 null 的 JSONObject

@GetMapping("/user/getUserId")
@ResponseBody
public JSONObject getUserId(@RequestParam String phoneNum) {
    JSONObject json = new JSONObject();
    Optional opt = userService.getUserId(phoneNum);
    opt.ifPresent(id -> json.put("userId", id));  // 只有非 null 才 put
    // 或显式判断
    // if (opt.isPresent()) json.put("userId", opt.get());
    return json;  // 無結果時返回 {}
}

3. 全局:配置 JSON 序列化忽略 null

// Spring Boot 2.x + Jackson
@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 字段
        return mapper;
    }
}

// 若用阿里 fastjson
@Bean
public HttpMessageConverter fastJsonConverter() {
    FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
    FastJsonConfig config = new FastJsonConfig();
    config.setSerializerFeatures(SerializerFeature.WriteMapNullValue); // 關鍵:關閉寫 null
    converter.setFastJsonConfig(config);
    return converter;
}

前端對接規範

$.getJSON('/user/getUserId', {phoneNum: phone}, function(data) {
    // data 保證是 {} 或 {"userId": 123},絕不包含 null
    if (data.userId) {
        $('#marcherId').val(data.userId);
    } else {
        alert('該手機號未註冊,請先註冊');
    }
}).fail(function(xhr) {
    console.error('請求失敗:', xhr.status, xhr.responseText);
});

核心原則總結

  1. 後端決不返回 null 值字段:要么不輸出該 Key,要么輸出具體值。
  2. Controller 統一返回非 null JSONObject:空結果返回 {},而非 null 或 {"k":null}。
  3. 全局序列化配置 NON_NULL:一勞永逸,避免業務代碼散落判空邏輯。
  4. 前端統一用 .fail() 處理 HTTP 非 2xx:區分業務無數據 (200 + {}) 與系統異常 (5xx)。

擴展:統一響應包裝器

public class R {
    private int code;      // 200 成功, 400 參數錯誤, 500 系統錯誤
    private String msg;
    private T data;
    // 靜態工廠方法
    public static  R ok(T data) { R r=new R<>(); r.code=200; r.data=data; return r; }
    public static  R fail(String msg) { R r=new R<>(); r.code=400; r.msg=msg; return r; }
}

// Controller
@GetMapping("/user/getUserId")
public R getUserId(@RequestParam String phoneNum) {
    return userService.getUserId(phoneNum)
        .map(R::ok)
        .orElse(R.ok(null));  // 返回 {"code":200,"data":null} 前端統一判斷 data 是否為 null
}

統一響應結構能徹底消除「null 值導致前端解析異常」這類低級問題,建議項目伊始即納入架構規範。

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