springboot springmvc 返回物件 為null的時候 的問題
springboot springmvc 返回物件 為null的時候
預設ajax前臺接收的時候會進入到error中。不想返回null。如果是物件,理想的是返回為[]
網上也有碰到這種問題的,百度不到,google
看裡面答案中的評論,應該是參考下面的:
@JsonSerialize public class EmptyJsonResponse { }
@RestController public class CompanyController { @RequestMapping(value = "/api/something", method = RequestMethod.GET) public ResponseEntity something() { return new ResponseEntity(new EmptyJsonResponse(), HttpStatus.OK); } }
總的來說,就是判斷是否為null,然後封裝一下。感覺每個地方都這麼處理的話,有點囉嗦了。
要不然還是過濾器或者其他地方攔截下,如果是ajax請求,是null或者空字元的情況,返回EmptyJsonResponse 類吧。
@JsonSerialize public class EmptyJsonResponse { }
參考:http://www.zhyea.com/2017/10/10/wrap-spring-boot-controller-response.html
方法一
第一種方式是替換掉RequestResponseBodyMethodProcessor,這需要使用一個MethodReturnValueHandler的裝飾類:
方法二
第二種方式基於ControllerAdvice和HttpMessageConverter實現。
首先用一個ResponseBodyAdvice類的實現包裝Controller的返回值:
如果Controller類的返回值沒有String型別的,僅有上面這個類就夠了。如果有String型別的返回值,就有可能遇到型別不匹配的問題。HttpMessageConverter是根據Controller的原始返回值型別進行處理的,而我們在ResponseAdvisor中改變了返回值的型別。如果HttpMessageConverter處理的目標型別是Object還好說,如果是其它型別就會出現問題,其中最容易出現問題的就是String型別,因為在所有的HttpMessageConverter例項集合中,StringHttpMessageConverter要比其它的Converter排得靠前一些。我們需要嘗試將處理Object型別的HttpMessageConverter放得靠前一些,這可以在Configuration類中完成:
我這裡參考方法二,另外要處理string這種情況的問題,否則返回string有問題
另外使用了這種方式(converters.add(0,mappingJackson2HttpMessageConverter);)後,如果想控制其他的,比如json返回實體中有null屬性的,自動不返回。全域性的配置default-property-inclusion: non_null 無效。屬性上面加@JsonInclude(JsonInclude.Include.NON_NULL) 有用,但是不可能一個個加。
後面查了下。如下,設定下mapper即可(後面有完整程式碼)(後面發現這種方法,針對返回null的情況不行,不會進入到beforeBodyWrite方法中。後面是採用了FastJsonHttpMessageConverter,詳情見後面)
ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
最終如下:
@ControllerAdvice
public class ResponseAdvisor implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?> > converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body,
MethodParameter returnType,
MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response) {
//null 或者空的處理 返回json 空物件[]
if (body==null||body.equals("")) {
return new EmptyJsonResponse();
}
//如果直接返回string 或者數字 ,包裝一下
if(body instanceof String ||body instanceof Number){
return ResultUtil.success(body);
}
return body;
}
@JsonSerialize
public class EmptyJsonResponse { }
}
下面這種方式,對null的返回沒辦法。進入不到上面的方法。
@Override
public void configureMessageConverters(List<HttpMessageConverter<?> > converters) {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); //屬性為NULL不序列化
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter= new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setObjectMapper(mapper);
converters.add(0,mappingJackson2HttpMessageConverter);//返回是string的話,預設把object的處理放在最前,否則ResponseAdvisor 處理字串返回時會報型別不一致的問題
}
採用如下方式 fastjson
@Override public void configureMessageConverters(List<HttpMessageConverter<?> > converters) { //針對欄位的處理 FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty,// List欄位如果為null,輸出為[],而非null SerializerFeature.WriteMapNullValue,//加上後,欄位為null的也會輸出 SerializerFeature.WriteNullStringAsEmpty,//字元型別欄位如果為null,輸出為”“,而非null SerializerFeature.WriteNullBooleanAsFalse,//Boolean欄位如果為null,輸出為false,而非null SerializerFeature.PrettyFormat //結果是否格式化,預設為false ); //日期格式化 fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); converter.setFastJsonConfig(fastJsonConfig); converters.add(0,converter);//返回是string的話,預設把這個放在最前,否則ResponseAdvisor 處理字串返回時會報型別不一致的問題 }