spring boot中使用jackson,自定义实现序列化和反序列化
大部分下,多个程序直接的沟通都离不开序列化和反序列化。前端后端的交互更是如此,所以目前框架提供的很多自带功能都帮我们实现了这些工作。然而!有时候可能遇到来自产品经理或者其他人的奇怪要求,使这些自带功能无法满足,只能自己搞小动作一下了。
1 自定义序列化的实现
这里很简单,就俩
- 序列化:针对某一数据类型的序列化实现接口JsonSerializer
- 反序列化:针对某一数据类型的反序列化实现接口JsonDeserializer
这里用时间类型举例吧,换其他类型也同理
序列化实现:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
*
* @Author: dong
* @Date: 2023/2/23 17:02
*/
public class MyLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
// 这里是自己的系列化逻辑
String format = DateTimeFormatter.ofPattern("序列化三侃时间:yyyy-MM-dd HH:mm:ss").format(date);
// 输处结果,这里注意“writeString”表示写出json的格式。写出的可以是多种格式,自己看具体方法
jsonGenerator.writeString(format);
}
}
反序列化实现
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
*
* @Author: dong
* @Date: 2023/2/23 17:02
*/
@Slf4j
public class MyLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private LocalDateTimeDeserializer deserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("反序列化三侃时间:yyyy-MM-dd HH:mm:ss"));
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
try{
LocalDateTime localDateTime = deserializer.deserialize(p, ctxt);
return localDateTime;
}catch (Exception e){
log.error("localDateTime类型反序列化失败!val={}",p.getText());
}
// 根据自己需求写个兜底的方案
throw new RuntimeException();
}
}
2 应用
2.1 针对某一个字段使用
这样使用只对注解的字段生效,不影响其他地方
@Data
public class Test{
@JsonSerialize(using = MyLocalDateTimeSerializer.class)
@JsonDeserialize(using = MyLocalDateTimeDeserializer.class)
private LocalDateTime param;
}
2.2 全局配置
当前springboot服务所有LocalDateTime 类型的值序列化都受影响
第一步 实现一个自己的序列化模块
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.PackageVersion;
import java.time.LocalDateTime;
// 自定义的序列化模块封装,多种也可以放在一起
public class MyJavaTimeModule extends SimpleModule {
public MyJavaTimeModule() {
super(PackageVersion.VERSION);
// ======================= 时间序列化规则 ===============================
this.addSerializer(LocalDateTime.class,
new MyLocalDateTimeSerializer());
// ======================= 时间反序列化规则 ==============================
this.addDeserializer(LocalDateTime.class,
new MyLocalDateTimeDeserializer());
}
}
第二步 使用这个配置
两种方式都可以
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObjectMapper.class)
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> {
builder.modules(new MyJavaTimeModule());
};
}
}
如果自己已经配置实现了WebMvcConfigurer并且有实现extendMessageConverters方法,可以用这种
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = converter.getObjectMapper();
objectMapper.registerModule(new MyJavaTimeModule());
converters.add(0, converter);
}
最后看一下效果的