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 { }
方法一
第一种方式是替换掉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 处理字符串返回时会报类型不一致的问题
}