说明
接口返回的json对象内的字段可能包含null值,前端可能还需要再对null做处理,判断、显示等
方案
除对象外,字段不会再返回null值
全局对返回null的处理
后端可使用注解@JacksonAllowNull允许字段返回null
类型 | 默认返回值 | 默认处理 |
---|---|---|
String | "" | 无 |
Boolean | false | 无 |
Integer,Float,Double,BigDecimal | 0 | 无 |
Long | 0 | 无 |
Array,List,Set | [] | 无 |
Date | null | FORMAT('yyyy-MM-dd HH:mm:ss'), timeZone(GMT+8) |
内容
JacksonAllowNull
/**
- 不处理null的数据
- @author miaoyj
- @version 1.0.0-SNAPSHOT
- @since 2020-07-09
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JacksonAllowNull {
}
JacksonHttpMessageConverter
@Component
public class JacksonHttpMessageConverter extends MappingJackson2HttpMessageConverter {
/**
- 构造函数
- @author miaoyj
- @since 2020-09-09
*/
public JacksonHttpMessageConverter() {
ObjectMapper objectMapper = getObjectMapper();
// 日期格式化
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 时区设置
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
objectMapper.setSerializerFactory(objectMapper.getSerializerFactory()
.withSerializerModifier(new MyBeanSerializerModifier()));
//解决 /instances/%5Bobject%20Object%5D/actuator/metrics
//https://github.com/codecentric/spring-boot-admin/issues/1517
objectMapper.addMixIn(InstanceId.class, InstanceIdMixin.class);
String[] pwdConstructor = new String[]{".*password$"};
objectMapper.registerModule(new AdminServerModule(pwdConstructor));
//解决domain.values.Registration cannot deserialize from Object
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Registration.class, ToStringSerializer.instance);
simpleModule.addDeserializer(Registration.class, new RegistrationDeserializer());
objectMapper.registerModule(simpleModule);
}
/**
- {@inheritDoc}
- 类型只支持application/json
- @author miaoyj
- @since 2020-09-09
*/
@Override
public ListgetSupportedMediaTypes() {
return CollUtil.newArrayList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN);
}
/**
- {@inheritDoc}
- JSON输出只处理Wrapper的包装类
- 不注释会导致springBootAdmin显示失败
- @author miaoyj
- @since 2020-09-09
*/
// @Override
// public boolean canWrite(Class> clazz, MediaType mediaType) {
// return ResultWrapper.class.isAssignableFrom(clazz);
// }
private class MyBeanSerializerModifier extends BeanSerializerModifier {
@Override
public List
for (Object beanProperty : beanProperties) {
BeanPropertyWriter writer = (BeanPropertyWriter) beanProperty;
/过滤允许为null的注解/
if (ObjectUtil.isNull(writer.getAnnotation(JacksonAllowNull.class))) {
if (isArrayType(writer)) {
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());
}
}
/* 防止Long精度丢失 */
// if(isLongType(writer)){
// writer.assignSerializer(new ToStringSerializer());
// }
}
return beanProperties;
}
private boolean isArrayType(BeanPropertyWriter writer) {
Class> clazz = writer.getType().getRawClass();
return clazz.isArray() || Collection.class.isAssignableFrom(clazz);
}
private boolean isStringType(BeanPropertyWriter writer) {
Class> clazz = writer.getType().getRawClass();
return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
}
private boolean isNumberType(BeanPropertyWriter writer) {
Class> clazz = writer.getType().getRawClass();
return Number.class.isAssignableFrom(clazz);
}
private boolean isLongType(BeanPropertyWriter writer) {
Class> clazz = writer.getType().getRawClass();
return Long.class.isAssignableFrom(clazz);
}
private boolean isBooleanType(BeanPropertyWriter writer) {
Class> clazz = writer.getType().getRawClass();
return clazz.equals(Boolean.class);
}
}
private class NullArrayJsonSerializer extends JsonSerializer
private class NullStringJsonSerializer extends JsonSerializer
private class NullNumberJsonSerializer extends JsonSerializer
private class NullBooleanJsonSerializer extends JsonSerializer
代码
https://gitee.com/miaoyinjun/jjche-boot