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,邏輯正常 |
public OptionalgetUserId(String phone) { Integer id = dao.selectUserId(phone); return Optional.ofNullable(id); }
@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; // 無結果時返回 {}
}
// 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);
});
null 值字段:要么不輸出該 Key,要么輸出具體值。{},而非 null 或 {"k":null}。NON_NULL:一勞永逸,避免業務代碼散落判空邏輯。.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 值導致前端解析異常」這類低級問題,建議項目伊始即納入架構規範。