Spring?Boot4實戰(zhàn)指南之Jackson2.x升級到3.x踩坑完全記錄
前言
最近在將公司的 Spring Cloud 微服務項目從 Spring Boot 3.2 + JDK 17 升級到 Spring Boot 4.0 + JDK 21 的過程中,Jackson 從 2.x 到 3.x 的升級是改動最大、坑最多的部分之一。
Jackson 3.0.0 于 2025 年 10 月 3 日正式發(fā)布,這是自 2013 年 Jackson 2.0 以來的首個大版本更新,經歷了近 8 年的開發(fā)。Spring Boot 4.0 也正式將 Jackson 3 作為默認 JSON 庫。
本文將結合實際項目代碼,從官方變更說明和真實踩坑經驗兩個維度,帶大家完整走一遍 Jackson 2.x → 3.x 的遷移過程。
一、Jackson 3.x 的核心變化概覽
在動手之前,我們先從官方文檔梳理 Jackson 3.x 相比 2.x 的核心變化:
1.1 包名和 Maven 坐標全面更換
這是最直觀的 Breaking Change:
| 維度 | Jackson 2.x | Jackson 3.x |
|---|---|---|
| Maven GroupId | com.fasterxml.jackson | tools.jackson |
| Java 包名 | com.fasterxml.jackson.* | tools.jackson.* |
| 注解包名 | com.fasterxml.jackson.annotation | 不變(仍用 2.x 的注解) |
特別注意:
jackson-annotations是個例外!Jackson 3.x 依賴的是jackson-annotations2.20 版本,注解的包名com.fasterxml.jackson.annotation保持不變。這意味著@JsonFormat、@JsonInclude、@JsonProperty等注解的 import 不需要改。
但 jackson-databind 中定義的注解(如 @JsonSerialize、@JsonDeserialize)會跟隨包名遷移到 tools.jackson.databind.annotation。
1.2 核心類重命名
Jackson 3.x 對大量核心類進行了重命名,目的是讓命名更加語義化:
| Jackson 2.x | Jackson 3.x | 說明 |
|---|---|---|
ObjectMapper | JsonMapper(推薦) | ObjectMapper 仍存在,但推薦使用格式特定子類 |
JsonSerializer<T> | ValueSerializer<T> | 序列化器基類 |
JsonDeserializer<T> | ValueDeserializer<T> | 反序列化器基類 |
SerializerProvider | SerializationContext | 序列化上下文 |
DeserializationContext | DeserializationContext | 不變 |
JsonProcessingException | JacksonException | 基礎異常類 |
JsonMappingException | DatabindException | 數據綁定異常 |
JsonParseException | StreamReadException | 解析異常 |
Module | JacksonModule | 避免與 java.lang.Module 沖突 |
TextNode | StringNode | JsonNode 子類型 |
1.3 異常體系變?yōu)?Unchecked
這是一個重大改變:Jackson 3.x 的所有異常都繼承自 RuntimeException,而不是 2.x 中的 IOException。
// Jackson 2.x JsonProcessingException extends IOException // checked // Jackson 3.x JacksonException extends RuntimeException // unchecked
這意味著你不再需要在方法簽名中聲明 throws 子句,但 catch 塊中的異常類型需要更新。
1.4 ObjectMapper 變?yōu)椴豢勺?/h3>
Jackson 3.x 中 ObjectMapper(及其子類型如 JsonMapper)是完全不可變的,必須通過 Builder 模式構建:
// Jackson 2.x - 可變配置
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.registerModule(new JavaTimeModule());
// Jackson 3.x - Builder 模式,不可變
JsonMapper mapper = JsonMapper.builder()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.changeDefaultPropertyInclusion(old ->
JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL))
.addModule(new SomeModule())
.build();
1.5 Java 8 時間模塊內置
Jackson 2.x 中需要單獨引入 jackson-datatype-jsr310 來支持 java.time 類型,3.x 已將其內置到 jackson-databind 中,無需額外依賴和注冊:
jackson-module-parameter-names→ 內置jackson-datatype-jdk8(Optional 等)→ 內置jackson-datatype-jsr310(java.time)→ 內置
1.6 默認配置變更
Jackson 3.x 修改了多個 Feature 的默認值,這些變更可能是升級后行為不一致的主因:
| Feature | 2.x 默認值 | 3.x 默認值 | 影響 |
|---|---|---|---|
FAIL_ON_UNKNOWN_PROPERTIES | true | false | 反序列化時遇到未知字段不再報錯 |
WRITE_DATES_AS_TIMESTAMPS | true | false | 日期默認輸出 ISO-8601 字符串而非時間戳 |
SORT_PROPERTIES_ALPHABETICALLY | false | true | 屬性按字母排序序列化 |
FAIL_ON_TRAILING_TOKENS | false | true | 解析后檢查是否有多余內容 |
FAIL_ON_NULL_FOR_PRIMITIVES | false | true | null 賦值給基本類型會報錯 |
FAIL_ON_EMPTY_BEANS | true | false | 空 Bean 序列化不再報錯 |
二、Spring Boot 4 中的 Jackson 3 集成方式
Spring Boot 4 對 Jackson 的集成方式有重大變化,理解這些變化是順利遷移的關鍵。
2.1 告別 Jackson2ObjectMapperBuilder
在 Spring Boot 3.x(Jackson 2.x)中,我們通常通過 Jackson2ObjectMapperBuilderCustomizer 來定制 ObjectMapper:
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> builder.indentOutput(true);
}在 Spring Boot 4.x(Jackson 3.x)中,Spring 不再提供 Jackson2ObjectMapperBuilder 的等價物,而是直接使用 Jackson 原生的 Builder,通過 JsonMapperBuilderCustomizer 進行定制:
@Bean
JsonMapperBuilderCustomizer jacksonCustomizer() {
return builder -> builder.enable(SerializationFeature.INDENT_OUTPUT);
}2.2 Jackson 2 和 3 可以共存
得益于包名完全不同(com.fasterxml.jackson vs tools.jackson),Jackson 2 和 3 可以在同一個 classpath 上共存。這為漸進式遷移提供了極大便利。
Spring Boot 4 同時提供了兩套版本的依賴管理,Spring Data Redis 等組件目前仍依賴 Jackson 2.x 的 API,兩套 Jackson 通過不同包名共存互不沖突。
三、實戰(zhàn)遷移:逐個擊破
下面結合我們項目的真實代碼,逐一講解遷移過程中的關鍵改動。
3.1 JacksonConfig:從 ObjectMapper Bean 到 JsonMapperBuilderCustomizer
這是改動最大的一個文件。我們原來通過 @Bean 直接創(chuàng)建 ObjectMapper 實例:
遷移前(Jackson 2.x):
@Configuration
@AutoConfigureBefore(JacksonAutoConfiguration.class)
public class JacksonConfig {
@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
private String pattern;
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
objectMapper.registerModule(javaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setTimeZone(TimeZone.getTimeZone(timezone));
return objectMapper;
}
private Module javaTimeModule() {
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LocalDateTime.class, getDateSerializer(pattern));
module.addDeserializer(LocalDateTime.class, getDateDeserializer(LocalDateTime.class));
// ... 其他類型
return module;
}
private <T> JsonSerializer<T> getDateSerializer(String pattern) {
return new JsonSerializer<>() {
@Override
public void serialize(T date, JsonGenerator gen, SerializerProvider provider)
throws IOException {
// 序列化邏輯
}
};
}
}
遷移后(Jackson 3.x):
@Configuration
public class JacksonConfig {
@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
private String pattern;
@Value("${spring.jackson.time-zone:}")
private String timezone;
@Bean
public JsonMapperBuilderCustomizer mossJacksonCustomizer() {
return builder -> {
String tz = StrUtil.emptyToDefault(timezone, ZoneId.systemDefault().getId());
SimpleModule module = new SimpleModule("MossDateTimeModule");
// 序列化
module.addSerializer(LocalDateTime.class, createDateSerializer(pattern));
module.addSerializer(LocalDate.class, createDateSerializer(DatePattern.NORM_DATE_PATTERN));
// ... 其他類型
// 反序列化
module.addDeserializer(LocalDateTime.class, createDateDeserializer(LocalDateTime.class));
module.addDeserializer(LocalDate.class, createDateDeserializer(LocalDate.class));
// ... 其他類型
builder.addModule(module);
builder.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
builder.changeDefaultPropertyInclusion(old ->
JsonInclude.Value.construct(
JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL));
builder.defaultTimeZone(TimeZone.getTimeZone(tz));
};
}
static <T> ValueSerializer<T> createDateSerializer(String pattern) {
return new ValueSerializer<T>() {
@Override
public void serialize(T date, JsonGenerator gen,
SerializationContext ctx) throws JacksonException {
// 序列化邏輯不變,只是參數類型改了
}
};
}
static <T> ValueDeserializer<T> createDateDeserializer(Class<T> clazz) {
return new ValueDeserializer<T>() {
@Override
public T deserialize(JsonParser parser,
DeserializationContext ctx) throws JacksonException {
String text = parser.getString(); // getText() -> getString()
// 反序列化邏輯不變
}
};
}
}
關鍵變化總結:
| 變化點 | Jackson 2.x | Jackson 3.x |
|---|---|---|
| 配置方式 | 直接創(chuàng)建 ObjectMapper Bean | 通過 JsonMapperBuilderCustomizer 定制 |
| 注解 | @AutoConfigureBefore | 不再需要(Customizer 自動生效) |
| 序列化器 | JsonSerializer<T> | ValueSerializer<T> |
| 反序列化器 | JsonDeserializer<T> | ValueDeserializer<T> |
| 序列化上下文 | SerializerProvider | SerializationContext |
| 異常類型 | IOException | JacksonException(unchecked) |
| 獲取文本 | parser.getText() | parser.getString() |
| 時間模塊 | JavaTimeModule(需手動注冊) | SimpleModule(內置 jsr310 支持) |
| 序列化包含策略 | mapper.setSerializationInclusion(...) | builder.changeDefaultPropertyInclusion(...) |
3.2 網關層:ObjectMapper 替換為 JsonMapper
在 Gateway 模塊中,之前到處 new ObjectMapper() 來做 JSON 序列化,這在 3.x 中需要改為注入 JsonMapper:
遷移前:
public class MossGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ...
ObjectMapper objectMapper = new ObjectMapper(); // 每次新建一個!
try {
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(objectMapper.writeValueAsBytes(ResultData.fail(...)))));
} catch (JsonProcessingException ex) {
log.error("對象輸出異常:", ex);
}
}
}
遷移后:
public class MossGlobalFilter implements GlobalFilter {
@Resource
private JsonMapper jsonMapper; // 注入不可變的 JsonMapper
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ...
try {
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(jsonMapper.writeValueAsBytes(ResultData.fail(...)))));
} catch (JacksonException ex) { // 異常類型變了
log.error("對象輸出異常:", ex);
}
}
}
改動點:
ObjectMapper→JsonMapper(通過@Resource注入,不再每次 new)JsonProcessingException→JacksonExceptioncom.fasterxml.jackson→tools.jackson的 import 替換
3.3 Redis 序列化:Jackson 2.x 和 3.x 共存的典型場景
這是一個非常典型的兩套 Jackson 共存場景。Spring Data Redis 4.0.x 的 Jackson2JsonRedisSerializer 仍基于 Jackson 2.x API,因此 Redis 配置類必須繼續(xù)使用 Jackson 2.x:
/**
* Redis 配置類
*
* 注意:雖然項目已將 REST 序列化遷移到 Jackson 3.x(tools.jackson.*),
* 但 Spring Data Redis 4.0.x 的 Jackson2JsonRedisSerializer 仍依賴
* Jackson 2.x(com.fasterxml.jackson.*),因此本類必須繼續(xù)使用 Jackson 2.x API。
* 兩套 Jackson 通過不同包名在 classpath 上共存,互不沖突。
*/
@Configuration
public class RedisConfig {
public void commonSerializerConfig(RedisTemplate<String, Object> redisTemplate) {
// 這里使用的是 com.fasterxml.jackson.databind.ObjectMapper
// 不是 tools.jackson.databind.json.JsonMapper!
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(
LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL);
om.registerModule(new JavaTimeModule());
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(om, Object.class);
redisTemplate.setValueSerializer(serializer);
}
}
Jackson2JsonRedisSerializer已被標記為@Deprecated(forRemoval = true),待 Spring Data Redis 升級適配 Jackson 3.x 后,應遷移至新的序列化方案。
3.4 Gateway 異常處理器:包名遷移
// 遷移前
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
public class CustomErrorWebExceptionHandler implements ErrorWebExceptionHandler {
private final ObjectMapper objectMapper;
// ...
try {
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(objectMapper.writeValueAsBytes(...))));
} catch (JsonProcessingException e) { ... }
}
// 遷移后
import tools.jackson.core.JacksonException;
import tools.jackson.databind.json.JsonMapper;
import org.springframework.boot.webflux.error.ErrorWebExceptionHandler; // 包名也變了!
public class CustomErrorWebExceptionHandler implements ErrorWebExceptionHandler {
private final JsonMapper jsonMapper;
// ...
try {
return response.writeWith(Mono.just(response.bufferFactory()
.wrap(jsonMapper.writeValueAsBytes(...))));
} catch (JacksonException e) { ... }
}
注意不僅 Jackson 的包名變了,Spring Boot 4 自身的一些類的包名也發(fā)生了變化,比如 ErrorWebExceptionHandler 從 org.springframework.boot.web.reactive.error 移到了 org.springframework.boot.webflux.error。
四、遷移清單:import 替換速查表
以下是實際項目中涉及的 import 替換對照表,可以直接用 IDE 的全局替換功能批量處理:
# Jackson 核心類 com.fasterxml.jackson.core.JsonGenerator → tools.jackson.core.JsonGenerator com.fasterxml.jackson.core.JsonParser → tools.jackson.core.JsonParser com.fasterxml.jackson.core.JsonProcessingException → tools.jackson.core.JacksonException com.fasterxml.jackson.databind.ObjectMapper → tools.jackson.databind.json.JsonMapper com.fasterxml.jackson.databind.JsonSerializer → tools.jackson.databind.ValueSerializer com.fasterxml.jackson.databind.JsonDeserializer → tools.jackson.databind.ValueDeserializer com.fasterxml.jackson.databind.SerializerProvider → tools.jackson.databind.SerializationContext com.fasterxml.jackson.databind.DeserializationContext → tools.jackson.databind.DeserializationContext com.fasterxml.jackson.databind.DeserializationFeature → tools.jackson.databind.DeserializationFeature com.fasterxml.jackson.databind.SerializationFeature → tools.jackson.databind.SerializationFeature com.fasterxml.jackson.databind.Module → tools.jackson.databind.JacksonModule com.fasterxml.jackson.databind.module.SimpleModule → tools.jackson.databind.module.SimpleModule # 時間模塊(已內置,通??梢詣h除 import) com.fasterxml.jackson.datatype.jsr310.JavaTimeModule → 已內置,無需單獨引入 # 注解(不變?。? com.fasterxml.jackson.annotation.JsonInclude → 不變 com.fasterxml.jackson.annotation.JsonFormat → 不變 com.fasterxml.jackson.annotation.JsonProperty → 不變
五、踩坑記錄
坑 1:JavaTimeModule 還是 SimpleModule?
Jackson 3.x 已將 jackson-datatype-jsr310 內置到 jackson-databind 中,因此 JavaTimeModule 不再作為獨立模塊存在于 tools.jackson 包下。
如果你之前通過 JavaTimeModule 注冊自定義的日期序列化/反序列化器,需要改為使用 SimpleModule:
// 2.x
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LocalDateTime.class, customSerializer);
// 3.x
SimpleModule module = new SimpleModule("CustomDateTimeModule");
module.addSerializer(LocalDateTime.class, customSerializer);
坑 2:setSerializationInclusion 被移除
ObjectMapper.setSerializationInclusion() 在 3.x 中被移除,需要通過 Builder 的 changeDefaultPropertyInclusion 方法替代:
// 2.x
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
// 3.x
builder.changeDefaultPropertyInclusion(old ->
JsonInclude.Value.construct(
JsonInclude.Include.NON_NULL,
JsonInclude.Include.NON_NULL));
坑 3:getText() → getString()
JsonParser.getText() 在 3.x 中被重命名為 getString()。如果你有自定義的反序列化器,IDE 可能不會自動提示這個變化:
// 2.x String text = jsonParser.getText(); // 3.x String text = jsonParser.getString();
坑 4:Redis 序列化器必須用 Jackson 2.x
Spring Data Redis 4.0 的 Jackson2JsonRedisSerializer 構造器只接受 com.fasterxml.jackson.databind.ObjectMapper,不兼容 Jackson 3.x 的 tools.jackson.databind.json.JsonMapper。
如果你在 RedisConfig 中也試圖遷移到 Jackson 3.x 的 JsonMapper,會遇到編譯錯誤。正確做法是 Redis 配置繼續(xù)使用 Jackson 2.x,等待 Spring Data Redis 后續(xù)版本的適配。
坑 5:FAIL_ON_UNKNOWN_PROPERTIES 默認值變化
Jackson 3.x 中 FAIL_ON_UNKNOWN_PROPERTIES 的默認值改為了 false,這實際上和大多數項目的期望一致。但如果你之前依賴這個特性來發(fā)現字段拼寫錯誤,升級后可能會靜默忽略錯誤的字段名。
如果你的項目原本就顯式配置了 false(大多數項目都是),那么這行配置可以刪掉了:
// 3.x 中這行可以刪除,因為默認就是 false builder.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
坑 6:WRITE_DATES_AS_TIMESTAMPS 默認值變化
這個影響范圍很大。Jackson 2.x 默認將日期序列化為時間戳數字,3.x 改為輸出 ISO-8601 字符串。如果你有大量依賴時間戳格式的前端代碼或單元測試,需要特別注意。
不過對于我們的項目來說,由于本身就通過自定義序列化器輸出 yyyy-MM-dd HH:mm:ss 格式,這個默認值變化沒有實際影響。
六、單元測試驗證
遷移完成后,編寫覆蓋性的單元測試非常重要。我們?yōu)?JacksonConfig 編寫了完整的測試用例,驗證所有日期類型的序列化/反序列化:
@Slf4j
public class JacksonConfigTest {
private JsonMapper buildMapper() {
SimpleModule module = new SimpleModule("MossDateTimeModule");
module.addSerializer(LocalDateTime.class,
JacksonConfig.createDateSerializer("yyyy-MM-dd HH:mm:ss"));
module.addDeserializer(LocalDateTime.class,
JacksonConfig.createDateDeserializer(LocalDateTime.class));
// ... 注冊其他類型
return JsonMapper.builder()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.changeDefaultPropertyInclusion(old ->
JsonInclude.Value.construct(
JsonInclude.Include.NON_NULL, JsonInclude.Include.NON_NULL))
.defaultTimeZone(TimeZone.getDefault())
.addModule(module)
.build();
}
@Test
public void testSerialize_LocalDateTime() throws Exception {
JsonMapper mapper = buildMapper();
DateTimeDto dto = new DateTimeDto();
dto.setLocalDateTime(LocalDateTime.of(2026, 4, 27, 15, 30, 0));
String json = mapper.writeValueAsString(dto);
assertTrue(json.contains("2026-04-27 15:30:00"));
assertFalse(json.contains("2026-04-27T15:30")); // 確認沒有 ISO 的 T 分隔符
}
@Test
public void testSerialize_nonNull() throws Exception {
JsonMapper mapper = buildMapper();
DateTimeDto dto = new DateTimeDto();
dto.setTitle("僅標題");
String json = mapper.writeValueAsString(dto);
assertTrue(json.contains("僅標題"));
assertFalse(json.contains("localDateTime")); // null 字段不應出現
}
}
重點測試項:
- LocalDateTime / LocalDate / LocalTime 的序列化格式是否符合預期
- Date / Timestamp / java.sql.Date 等傳統(tǒng)日期類型是否兼容
- 時區(qū)轉換邏輯是否正確(服務端時區(qū) ↔ 用戶時區(qū))
- NON_NULL 策略是否生效
- @JsonProperty(access = READ_ONLY) 注解是否正常工作
七、遷移步驟總結
整理一份可操作的遷移步驟清單:
Step 1:升級依賴
Spring Boot 4.0 會自動管理 Jackson 3.x 的版本,通常不需要顯式指定 Jackson 版本。
Step 2:全局替換 import
# 批量替換包名(注意排除 annotation 包)
find . -name "*.java" -exec sed -i '' \
's/com\.fasterxml\.jackson\.core/tools.jackson.core/g' {} +
find . -name "*.java" -exec sed -i '' \
's/com\.fasterxml\.jackson\.databind/tools.jackson.databind/g' {} +注意:不要替換
com.fasterxml.jackson.annotation,它保持不變。
Step 3:替換核心類名
ObjectMapper→JsonMapperJsonSerializer→ValueSerializerJsonDeserializer→ValueDeserializerSerializerProvider→SerializationContextJsonProcessingException→JacksonException
Step 4:改造配置類
- 將
@Bean ObjectMapper改為@Bean JsonMapperBuilderCustomizer - 刪除
@AutoConfigureBefore(JacksonAutoConfiguration.class) - 將
JavaTimeModule改為SimpleModule
Step 5:處理共存場景
- Redis、第三方 SDK 等仍使用 Jackson 2.x 的組件,保持原有代碼不變
- 添加注釋說明共存原因,方便后續(xù)遷移
Step 6:運行測試并修復
- 重點關注日期格式、屬性排序、null 值處理等行為變化
- 檢查
SORT_PROPERTIES_ALPHABETICALLY默認值變化對 JSON 對比測試的影響
八、參考資料
- Jackson 3.0 Release Notes — 完整變更列表
- Jackson 3 Migration Guide — 官方遷移指南
- Introducing Jackson 3 support in Spring — Spring 官方博客
- Jackson 3.0.0 GA Released — Jackson 作者博客
- Why Upgrade to Jackson 3? — 升級收益分析
- OpenRewrite Recipe for Jackson 2→3 — 自動化遷移工具
總結
Jackson 2.x → 3.x 的升級雖然是 Breaking Change,但整體遷移路徑比較清晰:
- 包名替換是工作量最大但最機械的部分,可以批量處理
- 核心類重命名需要理解新舊對照關系,但命名更加直觀
- 配置方式變更(Builder 模式)是設計理念的升級,代碼更加安全
- 默認值變化需要逐一檢查對業(yè)務的影響
- Jackson 2/3 共存讓漸進式遷移成為可能
Jackson 3 在安全性、API 設計、默認配置和性能上都有明顯提升,建議在升級 Spring Boot 4.0 時同步完成遷移。
到此這篇關于Spring Boot4實戰(zhàn)指南之Jackson2.x升級到3.x踩坑的文章就介紹到這了,更多相關Jackson2.x升級到3.x踩坑內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用Springboot搭建OAuth2.0 Server的方法示例
這篇文章主要介紹了使用Springboot搭建OAuth2.0 Server的方法示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08

