前言
由于项目由SpringBoot3.x升级到SpringBoot4.x,内置的jackson2升级为jackson3,包名改变以及部分类已经不再向下兼容,记录下升级过程中的一些问题
统一的序列化配置
SpringBoot3.x中的LocalDateTime序列化以及反序列化配置,如果使用的是Jackson2ObjectMapperBuilderCustomizer的话,由于该类在jackson3中已经不存在,需要改为使用jackson3中JsonMapperBuilderCustomizer的方式,并且写法略有改变
问题点
- 前后端请求中,时间类型的请求响应参数,统一使用 yyyy-MM-dd HH:mm:ss 格式
- 由于前端对于后端结果中,Long类型数据的精度缺失,为避免前端处理,统一由后端将Long类型数据序列化为String类型数据返回
- 对jackson添加统一的Long类型序列化后,响应类中,无需在Long参数中重复添加@JsonSerialize(using = ToStringSerializer.class)注解
代码示例
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.core.JsonParser;
import tools.jackson.databind.DeserializationContext;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ValueDeserializer;
import tools.jackson.databind.ValueSerializer;
import tools.jackson.databind.module.SimpleModule;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class JacksonConfig {
private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
@Bean
public JsonMapperBuilderCustomizer jsonCustomizer() {
return builder -> {
// 添加 LocalDateTime 的序列化与反序列化
builder.addModule(
new SimpleModule()
// Long 的序列化
.addSerializer(Long.class, new LongSerializer())
// LocalDateTime 的序列化
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer())
// LocalDateTime 的反序列化
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer())
);
};
}
/**
* Long 的序列化
*/
private static class LongSerializer extends ValueSerializer<Long> {
@Override
public void serialize(Long value, JsonGenerator gen, SerializationContext ctxt) throws JacksonException {
if (value != null) {
gen.writeString(value.toString());
}
}
}
/**
* LocalDateTime 的序列化
*/
private static class LocalDateTimeSerializer extends ValueSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializationContext ctxt) throws JacksonException {
if (value != null) {
gen.writeString(value.format(DATE_TIME_FORMATTER));
} else {
gen.writeNull();
}
}
}
/**
* LocalDateTime 的反序列化
*/
private static class LocalDateTimeDeserializer extends ValueDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws JacksonException {
String dateString = p.getString();
if (dateString == null || dateString.trim().isEmpty()) {
return null;
}
return java.time.LocalDateTime.parse(dateString, DATE_TIME_FORMATTER);
}
}
}
部分jackson包名需要替换 com.fasterxml.jackson -> tools.jackson
在 Jackson 3 中,@JsonProperty 注解仍然有效,且核心功能(字段重命名、读写控制、必填校验等)保持不变。
不过需要注意以下细节:
- 包路径不变:仍为
com.fasterxml.jackson.annotation.JsonProperty,无需修改导入语句。 - 兼容性保障:Jackson 3 对该注解的支持是完全向后兼容的,基于 Jackson 2 开发的代码中使用
@JsonProperty的逻辑可直接迁移。 - 搭配新构建器:若结合 Jackson 3 新的
JsonMapper.Builder构建ObjectMapper,@JsonProperty的注解逻辑也会被正常识别和处理。
例如,以下代码在 Jackson 3 中依然能正常工作:
public class User {
@JsonProperty("user_id")
private Long id;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
}