本次改造主要解决以下问题:spring
基础篇json
进阶篇数组
spring默认状况下使用jackson做为bean转json处理工具,因此我就以spring的默认配置为基础,添加一些自定义的配置。由于定制rest接口没啥逻辑可言,主要就是熟悉一下各个配置在那边设置,因此先给出最终的配置文件bash
@Configuration
public class RestResponseConfig {
@Autowired(required = false)
private List<BeanSerializerModifier> modifierList;
@Bean
public HttpMessageConverters message() {
return new HttpMessageConverters(getHttpMessageConverter());
}
private HttpMessageConverter getHttpMessageConverter() {
if (modifierList != null && modifierList.size() > 0) {
return new MappingJackson2HttpMessageConverter(wrapper());
}
return new MappingJackson2HttpMessageConverter(getObjectMapper());
}
private ObjectMapper wrapper() {
ObjectMapper objectMapper = getObjectMapper();
objectMapper.setSerializerFactory(getSerializerFactory(objectMapper));
return objectMapper;
}
private SerializerFactory getSerializerFactory(ObjectMapper objectMapper) {
SerializerFactory factory = objectMapper.getSerializerFactory();
for (BeanSerializerModifier modifier : modifierList) {
factory = factory.withSerializerModifier(modifier);
}
return factory;
}
private ObjectMapper getObjectMapper() {
return Jackson2ObjectMapperBuilder.json()
.modules(getModule())
.featuresToEnable(enableFeature())
.featuresToDisable(disableFeature())
.serializationInclusion(JsonInclude.Include.NON_EMPTY)
.timeZone(TimeZone.getTimeZone(ZoneId.of("GMT+8")))
.build();
}
private Module getModule() {
SimpleModule module = new SimpleModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
return module;
}
private Object[] enableFeature() {
return new Object[]{
SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS
// , JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS
};
}
private Object[] disableFeature() {
return new Object[]{SerializationFeature.WRITE_DATES_AS_TIMESTAMPS};
}
}
复制代码
基础篇问题网络
在getObjectMapper方法下面serializationInclusion属性,jackson提供了以下集中选择经常使用的就是ALWAYS,NON_NULL,NON_EMPTYapp
ALWAYS,
NON_NULL,
NON_ABSENT,
NON_EMPTY,
NON_DEFAULT,
CUSTOM,
USE_DEFAULTS;
复制代码
举个例子,如今有一个pojoide
public class Pojo {
private String name;
}
复制代码
当他做为返回值的时候,若是你的配置为ALWAYS,那么即使name为null,你也会收到返回值。工具
{
"name":null
}
复制代码
可是当选择NON_NULL的时候,若是name为null的话,咱们就不会收到这个属性了。post
{
}
复制代码
若是name不为null,而是"",这样的话接口仍是会收到返回ui
{
"name":""
}
复制代码
若是选择NON_EMPTY,那么只有当那么不为null,且不为"",接口才会收到返回值。
在默认配置下 LocalDateTime 类的格式是这样的
"time":"2019-10-21T12:29:34"
复制代码
其实这个到不是说必定要改,而是各类需求的变化层出不穷,我遇到过有的地方专门以 yyyyMMddHHmmss 这种格式来传递时间的。因此咱们仍是须要掌握一下自定义的方法。
private Module getModule() {
SimpleModule module = new SimpleModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
return module;
}
复制代码
方法就在getModule这儿。SimpleModule这个类,咱们这样配置的意思就是若是遇到LocalDateTime类,就以 LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))来处理该类的序列化,反序列化也同样。因此在这边指定日期的格式就能够了。
在默认状况下 char[] 数组序列化的时候会变为字符串
private char[] chars;
//输入
"chars":["a","b"]
//输出
"chars": "ab"
复制代码
该配置在enableFeature方法中
SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS
复制代码
只要设置了WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS这个属性,char[] 数组,即可以以数组的形式序列化了。
基础篇到这儿就结束了,已经差很少够解决通常性的需求。
进阶篇问题
不要问我为何要这样返回,由于我遇到的下游厂家是这么要求的。。。
要完成这个需求,首先得自定义一个序列化组件
@Component
public class NullStringSerializer extends StdSerializer<Object> {
public NullStringSerializer() {
super(Object.class);
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString("");
}
}
复制代码
其次将该序列化组件设置为String类的null序列化组件
public class CustomNullSerializerModifier extends BeanSerializerModifier {
@Autowired
private NullStringSerializer nullStringSerializer;
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (BeanPropertyWriter writer : beanProperties) {
Class<?> rawClass = writer.getType().getRawClass();
if(rawClass.isAssignableFrom(String.class)){
writer.assignNullSerializer(nullStringSerializer);
}
}
return beanProperties;
}
}
复制代码
这样咱们上面的配置文件就能够读取到这个配置了。当String为null的时候,接口就会返回""了。