前言
各位同学可能遇到过下述问题,在项目开发中,后端是以Json格式的数据返回给前端,但是对于数据为空的字段,可能出现NULL,这让前端同学很痛苦,于是他们想,针对那些为null的字段,后端能不能把String类型的数据返回空字符串,int类型的数据返回0,集合和数组返回[],这样多方便呢!OK,既然这样的话就满足他们的要求,本文利用Spring自带的Json转化器,将返回给前端的数据进行处理,见下文所示。
一、编写Json数据转化器
/**
* @作者 yangs
* @日期 2022/1/20
* @描述 json数据转化器
*/
public class JacksonHttpMessageConverter extends MappingJackson2HttpMessageConverter {
/**
* 处理数组类型的null值
*/
public class NullArrayJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
if (value == null) {
jgen.writeStartArray();
jgen.writeEndArray();
}
}
}
/**
* 处理字符串类型的null值
*/
public class NullStringJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeString(StringUtils.EMPTY);
}
}
/**
* 处理数字类型的null值
*/
public class NullNumberJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeNumber(0);
}
}
/**
* 处理布尔类型的null值
*/
public class NullBooleanJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeBoolean(false);
}
}
public class MyBeanSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
//循环所有的beanPropertyWriter
for (Object beanProperty : beanProperties) {
BeanPropertyWriter writer = (BeanPropertyWriter) beanProperty;
//判断字段的类型,如果是array,list,set则注册nullSerializer
if (isArrayType(writer)) {
//给writer注册一个自己的nullSerializer
writer.assignNullSerializer(new NullArrayJsonSerializer());
} else if (isNumberType(writer)) {
writer.assignNullSerializer(new NullNumberJsonSerializer());
} else if (isBooleanType(writer)) {
writer.assignNullSerializer(new NullBooleanJsonSerializer());
} else if (isStringType(writer)) {
writer.assignNullSerializer(new NullStringJsonSerializer());
}
}
return beanProperties;
}
/**
* 是否是数组
*/
private boolean isArrayType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return clazz.isArray() || Collection.class.isAssignableFrom(clazz);
}
/**
* 是否是string
*/
private boolean isStringType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
}
/**
* 是否是int
*/
private boolean isNumberType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return Number.class.isAssignableFrom(clazz);
}
/**
* 是否是boolean
*/
private boolean isBooleanType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return clazz.equals(Boolean.class);
}
}
public JacksonHttpMessageConverter() {
getObjectMapper().setSerializerFactory(getObjectMapper().getSerializerFactory().withSerializerModifier(new MyBeanSerializerModifier()));
}
}
二、编写MVC配置文件
接下来我们要写一个MVC的配置类,继承WebMvcConfigurationSupport类,并重写configureMessageConverters()方法,在这里方法中,我们要把上面定义的Json转换工具加载进来,来实现我们想要的功能。
/**
* @作者 yangs
* @日期 2022/1/20
* @描述 MVC的配置类
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
// 文件映射路径
@Value("${fileMappingPath}")
private String fileMappingPath;
/**
* @作者 yangs
* @日期 2022/1/20
* @描述 返回给前端的json格式转化器
*/
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
converters.add(new JacksonHttpMessageConverter());
}
}
到目前为止,我们已经实现了想要的功能,把String类型的null转成"",把Integer类型的null转成0,把空集合和数组转成[]。但是继承WebMvcConfigurationSupport后,可能会出现一些坑,比如静态资源获取的问题。继续往下看,没准可以防止埋雷。
三、防雷警告
继承WebMvcConfigurationSupport类会使application.yml中配置的静态资源映射失效,如果你在配置文件中配置了如下代码,一定要警惕:
spring:
mvc:
static-path-pattern: /image/**
resources:
static-locations: file:E:/picture/
当我们继承WebMvcConfigurationSupport类时,会是配置文件的静态资源映射失效,所以我们需要另一种解决方法,只需在WebMvcConfigurationSupport的子类中重写addResourceHandlers()方法即可,如下所示:
/**
* @作者 yangs
* @日期 2022/1/20
* @描述 MVC的配置类
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* @作者 yangs
* @日期 2022/1/20
* @描述 返回给前端的json格式转化器
*/
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
converters.add(new JacksonHttpMessageConverter());
}
// 文件映射路径
@Value("${fileMappingPath}")
private String fileMappingPath;
/**
* @作者 yangs
* @日期 2022/1/20
* @描述 配置静态资源访问路径
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//通过image获取静态资源
registry.addResourceHandler("/image/**").addResourceLocations(fileMappingPath);
}
}
你也可以查看我的另一篇文章,查阅如何在SpringBoot中访问本地的静态资源,SpringBoot访问本地静态资源。