1. 程式人生 > >springboot springmvc 返回物件 為null的時候 的問題

springboot springmvc 返回物件 為null的時候 的問題

springboot springmvc 返回物件 為null的時候 

預設ajax前臺接收的時候會進入到error中。不想返回null。如果是物件,理想的是返回為[] 

網上也有碰到這種問題的,百度不到,google

https://stackoverflow.com/questions/44837846/spring-boot-return-a-empty-json-instead-of-empty-body-when-returned-object-is-n

看裡面答案中的評論,應該是參考下面的:

https://codingexplained.com/coding/java/spring-framework/returning-empty-json-object-spring-framework

@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 處理字串返回時會報型別不一致的問題
}