Jackson 1.x到2.x的演进与Spring集成

Jackson 从 1.x 到 2.x 的演进,不仅是一次技术升级,更深刻影响了 Spring 生态(尤其是 Spring MVC 和 Spring Boot)的 JSON 处理方式。下面从 Jackson 自身差异 、Spring 对 Jackson 的集成变迁 、实际开发中的迁移注意事项 三个维度,系统梳理这一历程。


一、Jackson 1.x vs 2.x:核心差异回顾(精要版)

维度 Jackson 1.x (org.codehaus.jackson) Jackson 2.x (com.fasterxml.jackson)
包名 org.codehaus.jackson.* com.fasterxml.jackson.*
模块化 核心 + mapper 混合 拆分为 core / annotations / databind
注解位置 org.codehaus.jackson.map.annotate.* com.fasterxml.jackson.databind.annotation.*
过滤 null @JsonSerialize(include = Inclusion.NON_NULL) 废弃 → 改用 @JsonInclude(Include.NON_NULL)
异常体系 JsonProcessingException 等 更细粒度(JsonParseException, DatabindException)
扩展性 基础支持 更强(支持自定义 Module、AnnotationIntrospector 等)
维护状态 已停止(~2013) 活跃维护(当前 2.17+)

✅ 关键结论 :两者二进制不兼容,不能共存于 classpath(会冲突)。


二、Spring 项目中 Jackson 的集成变迁

1. Spring Framework 3.x 时代(~2010--2013)

  • 默认使用 Jackson 1.x。

  • 需手动添加依赖:

    xml 复制代码
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.13</version>
    </dependency>
  • 在 Spring MVC 中启用 JSON:

    xml 复制代码
    <mvc:annotation-driven />
    <!-- 自动检测 classpath 下的 Jackson 1.x -->

⚠️ 此时若想用 Jackson 2.x,需显式配置 MappingJackson2HttpMessageConverter(名字带 "2" 就是为区分 1.x)。


2. Spring Framework 4.x 起(2013+):全面拥抱 Jackson 2.x

  • 默认且仅支持 Jackson 2.x。
  • 移除对 Jackson 1.x 的自动配置支持。
  • 新增核心类:
    • MappingJackson2HttpMessageConverter(取代旧的 MappingJacksonHttpMessageConverter)
    • Jackson2ObjectMapperBuilder
  • 自动配置条件:classpath 存在 com.fasterxml.jackson.databind.ObjectMapper
Spring Boot 的推动(2014+)
  • Spring Boot 1.0+ 默认内嵌 Jackson 2.x。

  • starter 依赖自动引入:

    xml 复制代码
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- 传递依赖 jackson-databind 2.x -->
    </dependency>
  • 通过 application.properties 轻松配置:

    properties 复制代码
    spring.jackson.serialization.write-dates-as-timestamps=false
    spring.jackson.default-property-inclusion=NON_NULL

✅ 从此,新项目几乎不再接触 Jackson 1.x。


3. Spring Boot 2.x / 3.x:深度集成与现代化

  • Jackson 2.9+ ~ 2.15+ 成为事实标准。

  • 支持 Java 8+ 特性(Optional, LocalDateTime 等开箱即用)。

  • 通过 Jackson2ObjectMapperBuilderCustomizer 定制:

    java 复制代码
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        return builder -> builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
    }
  • Spring Boot 3.x(基于 Jakarta EE 9+):

    • 包名从 javax.* → jakarta.*
    • 但 Jackson 不受影响 (仍用 com.fasterxml.jackson)

三、实际开发中的关键差异与迁移要点

场景 1:自定义序列化器

Jackson 1.x(已过时):
java 复制代码
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

public class MySerializer extends JsonSerializer<MyClass> {
    @Override
    public void serialize(MyClass value, JsonGenerator jgen, SerializerProvider provider) {
        jgen.writeString("custom");
    }
}
Jackson 2.x(现代写法):
java 复制代码
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class MySerializer extends JsonSerializer<MyClass> {
    @Override
    public void serialize(MyClass value, JsonGenerator gen, SerializerProvider serializers) {
        gen.writeString("custom");
    }
}

🔁 只需改 import,逻辑几乎不变。


场景 2:注解使用变更

❌ Jackson 1.x 写法(在 2.x 中无效):
java 复制代码
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
private String name;
✅ Jackson 2.x 正确写法:
java 复制代码
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
    private String name;
}
// 或字段级
@JsonInclude(Include.NON_EMPTY)
private List<String> tags;

📌 这是最常见的迁移错误!


场景 3:Spring 配置类变更

Spring 3.x + Jackson 1.x:
java 复制代码
@Bean
public MappingJacksonHttpMessageConverter jacksonConverter() {
    return new MappingJacksonHttpMessageConverter();
}
Spring 4.x+ + Jackson 2.x:
java 复制代码
@Bean
public MappingJackson2HttpMessageConverter jackson2Converter() {
    return new MappingJackson2HttpMessageConverter();
}

注意类名多了 "2"!

但在 Spring Boot 中,通常无需手动配置,自动装配即可。


场景 4:依赖冲突排查

若项目同时引入了 Jackson 1.x 和 2.x(例如老 jar 传递依赖),会出现:

  • ClassNotFoundException
  • NoSuchMethodError
  • AbstractMethodError

解决方法:

bash 复制代码
# Maven 查看依赖树
mvn dependency:tree | grep jackson

# 排除旧版本
<exclusion>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
</exclusion>

四、总结:演进脉络与最佳实践

时间线 技术栈 建议
2010--2013 Spring 3.x + Jackson 1.x 仅维护旧系统
2013--2016 Spring 4.x + Jackson 2.x 过渡期 主动迁移,替换包名和注解
2016 至今 Spring Boot + Jackson 2.6+ 使用 @JsonInclude,避免 include 属性
未来 Spring Boot 3.x + Jackson 2.15+ 拥抱 Java 17+,利用新特性(record、sealed class)

✅ 最佳实践(现代 Spring Boot 项目):

  1. 不要手动管理 Jackson 依赖 ,由 spring-boot-starter-web 控制版本。
  2. 用 @JsonInclude 替代旧的 include 属性。
  3. 自定义序列化/反序列化时,继承 StdSerializer / StdDeserializer(比直接继承基类更安全)。
  4. 全局配置优先使用 application.yml ,而非硬编码 ObjectMapper。

如果你正在维护一个从 Spring 3.x 升级到 Spring Boot 的老系统,重点检查:

  • 所有 import org.codehaus.jackson... → 替换为 com.fasterxml.jackson...
  • 所有 @JsonSerialize(include=...) → 改为 @JsonInclude(...)
  • 确保 classpath 没有残留 Jackson 1.x 的 jar

这样就能平滑过渡到现代 Jackson 2.x 生态。

相关推荐
李兆龙的博客12 小时前
问津集 #26:Lakebase——Postgres 的版本化页面存储、数据库分支与计算弹性
数据库
Joy T12 小时前
Spring AI 项目中的 pom.xml、application.yml 与 Nacos:从依赖管理到运行配置
spring·nacos·pom.xml·profile·参数配置·application.yml
倔强的石头_14 小时前
聊聊金仓KFS:一款把数据同步软件做扎实的产品
数据库
闲云野鹤在人间14 小时前
MySQL|从理论、安装、备份到主从复制、MHA高可用详解
linux·运维·数据库·mysql·云计算
禾小西14 小时前
Redis:从两大维度和三大主线建立知识体系
数据库·redis·缓存
禾小西15 小时前
Redis 数据结构:快速的 Redis 有哪些慢操作?
数据结构·数据库·redis
数据库小学妹15 小时前
数据共享交换平台选型:交换方式对比与避坑指南
数据库·信创·数据同步·数据交换平台·政务数据共享·数据共享交换平台·数据库底座
要开心吖ZSH16 小时前
MySQL 慢 SQL 排查操作手册-个人笔记版
java·笔记·sql·mysql·慢查询
loong_XL17 小时前
决策模型做内容安全检测:从踩坑到上线
数据库·安全·jev·决策模型
这个DBA有点耶17 小时前
数据库双轨并行实战:全量并行策略、增量延迟控制、双向回切与一致性校验
数据库·架构·dba