一、核心要点(必掌握,迁移基础)
1. 环境基线升级: 最低支持 jdk 17(2.x 为 jdk 8),项目需先完成 jdk 升级适配。
2. 包名与依赖变更:
- maven groupid:com.fasterxml.jackson → tools.jackson(jackson-annotations 除外,仍用 2.x 版本)java 导入包:
- com.fasterxml.jackson.xxx → tools.jackson.xxx(com.fasterxml.jackson.annotation 保留不变)
3. 核心 api 不可变性: objectmapper(及子类)、jsonfactory(及子类)变为完全不可变,必须通过 builder 模式构建(不再支持直接 set 配置)。
jsonmapper m=jsonmapper.builder().build(); jsonfactory f = jsonfactory.builder().build();
4 .异常体系重构: 所有异常改为非检查型(继承 runtimeexception),核心异常类重命名(如 jsonprocessingexception → jacksonexception)。 5. 格式绑定强制化: 必须使用格式对齐的 objectmapper 子类(如 jsonmapper、yamlmapper、xmlmapper),禁止 new objectmapper(new yamlfactory()) 写法。 6. java 8 模块内置: jackson-module-parameter-names、jackson-datatype-jdk8、jackson-datatype-jsr310 已整合到 jackson-databind,无需单独依赖。
二、关键变更(影响代码改造)
1. 内容移除
- 版本标记为 @deprecated 的方法、字段、类全部删除( 参考 2.20 javadoc 替换为替代方案)。
- 移除模块 jackson-module-jsonschema 、jackson-datatype-hibernatex。
- 移除功能:格式自动检测(dataformatdetector 等相关类)、objectmapper.canserialize()/candeserialize() 方法。
- jsonparser
canwritebinarynatively(), canwriteformattednumbers()分别替为streamwritecapability.can_write_binary_natively / streamwritecapability.can_write_formatted_numbers - jsonfactory
getcodec() 、 setcodec()被移除 - com.fasterxml.jackson.databind.mappingjsonfactory 被移除
- com.fasterxml.jackson.core.objectcodec 被移除,替换为 2 个独立的接口: tools.jackson.core.objectreadcontext(实现类:deserializationcontext) , tools.jackson.core.objectwritecontext(实现类: serializationcontext )
- tools.jackson.databind.jsontype.impl.laissezfairesubtypevalidator 已不再公开。请使用 basicpolymorphictypevalidator.builder()
- jsongenerator.setprettyprinter() 被移除
- request payload 能力被移除
- bufferrecyclers.system_property_track_reusable_buffers 被移除
- tokenstreamfactory.feature.use_thread_local_for_buffer_recycling 被移除
- 在 jackson 2.x 的 jsonfactory 类中,接受 url 参数的工厂方法将被移除
2. 类与方法重命名(高频变更)
| 2.x 旧名称 | 3.x 新名称 | ||
|---|---|---|---|
| jsonprocessingexception | jacksonexception(基类) | ||
| jsonparseexception | streamreadexception | ||
| jsoneofexception | unexpectedendofinputexception | jsongenerationexception | streamwriteexception |
| jsongenerator.writeobject() | jsongenerator.writepojo() | ||
| jsongenerator.getcurrentvalue() | jsongenerator.currentvalue() | jsongenerator.setcurrentvalue() | jsongenerator.assigncurrentvalue() |
| jsongenerator.getcodec() | jsongenerator.objectwritecontext() | ||
| jsonparser.getcurrentlocation() | jsonparser.currentlocation() | ||
| jsonparser.gettokenlocation() | jsongenerator.currenttokenlocation() | ||
| jsonparser.getcurrentvalue() | jsonparser.currentvalue() | ||
| jsonparser.setcurrentvalue() | jsonparser.assigncurrentvalue() | ||
| jsonparser."xxxtextyyy"() 格式 如(gettextcharacters()) | jsonparser."xxxstringyyy"() 格式 如(getstringcharacters()) | ||
| jsonparser.getcodec() | jsonparser.objectreadcontext() | ||
| jsontoken.field_name | jsontoken.property_name | ||
| jsonfactory | tokenstreamfactory | ||
| jsonstreamcontext | tokenstreamcontext | ||
| jsonlocation | tokenstreamlocation | ||
| jsondeserializer | valuedeserializer | ||
| jsonserializer | valueserializer | ||
| jsonmappingexception | databindexception | ||
| module | jacksonmodule(避免与 jdk module 冲突) | ||
| textnode | stringnode | ||
| beanserializermodifier | valueserializermodifier | ||
| beandeserializermodifier | valuedeserializermodifier | ||
| serializerprovider | serializationcontext | ||
| textnode | stringnode | ||
| annotationintrospector.finddefaultcreator() | findpreferredcreator() | ||
| jsonnode.elements() | jsonnode.values() | ||
| containerserializer | stdcontainerserializer | ||
| objectmapper.getregisteredmoduleids() | objectmapper.registeredmodules() | ||
| treenode.propertynames() 的返回类型 | 从 iterator 更改为 collection | ||
| treenode.iscontainernode() | treenode. iscontainer() | ||
| jsongenerator.feature.auto_close_json_content | jsongenerator.feature.auto_close_content |
3. 配置默认值变更(易引发行为差异)
| 枚举 | 配置项 | 2.x 默认值 | 3.x 默认值 | 影响说明 |
|---|---|---|---|---|
| deserializationfeature | fail_on_trailing_tokens | 关闭 | 开启 | 校验 json 末尾是否存在多余字符(如解析对象后还有额外的逗号 / 字符),提升数据合法性校验,但会增加少量解析开销;若输入数据可信(如内部系统交互),可关闭以恢复 2.x 性能。 |
| fail_on_unknown_properties | 开启 | 关闭 | 反序列化时遇到目标类不存在的字段,不再抛出 unrecognizedpropertyexception,而是直接忽略;可能掩盖字段名拼写错误、接口字段变更等问题,建议在测试环境开启该配置,生产环境按需关闭。 | |
| read_enums_using_to_string | 关闭 | 开启(迁移至 enumfeature) | 反序列化枚举时,默认按 enum.tostring() 结果匹配(2.x 默认按枚举名称 / 索引);若枚举重写了 tostring(),会改变反序列化逻辑,需确认枚举值映射规则,或显式配置 enumfeature.read_enums_using_to_string=false 回退。 | |
| fail_on_null_for_primitives | 关闭 | 开启 | 反序列化时,若基本类型(int/long/boolean 等)字段接收到 null 值,会抛出 databindexception;2.x 会默认赋值基本类型默认值(如 int=0),可能暴露空值处理漏洞,但也会导致原有依赖 “空值转默认值” 的代码报错。 | |
| serializationfeature | write_enums_using_to_string | 关闭 | 开启(迁移至 enumfeature) | 序列化枚举时,默认输出 enum.tostring() 结果(2.x 默认输出枚举名称);若枚举重写了 tostring(),序列化结果会变化,需统一枚举序列化规则,或配置 enumfeature.write_enums_using_to_string=false。 |
| fail_on_empty_beans | 开启 | 关闭 | 序列化无属性 / 无 getter 的空 bean 时,不再抛出 jsonmappingexception,而是输出空对象 {};避免因 bean 结构临时调整导致序列化失败,但需注意空对象可能不符合下游系统的解析预期。 | |
| fail_on_order_map_by_incomparable_key | 开启 | 关闭 | 序列化 sortedmap 时,若 key 不实现 comparable 接口,不再抛出异常;2.x 会强制校验 key 的可比较性,3.x 放宽限制,但可能导致 map 排序混乱,需确保 sortedmap 的 key 符合 comparable 规范。 | |
| write_durations_as_timestamps | 开启 | 关闭(迁移至 datetimefeature) | 序列化 java.time.duration 时,默认输出 iso-8601 字符串(如 pt1h30m),而非 2.x 的毫秒数时间戳;需确认下游系统是否兼容 duration 的字符串格式,或配置 datetimefeature.write_durations_as_timestamps=true 回退。 | |
| write_dates_as_timestamps | 开启 | 关闭(迁移至 datetimefeature) | 序列化日期时间类型(如 localdatetime/date)时,默认输出 iso-8601 字符串(如 2025-12-09t10:00:00),而非 2.x 的毫秒时间戳;会改变接口返回的日期格式,需同步更新前端 / 下游系统的解析逻辑。 | |
| write_date_keys_as_timestamps | 关闭 | 关闭(迁移至 datetimefeature) | 无默认值变化,但配置项归属从 serializationfeature 迁移至 datetimefeature;代码中需替换配置引用路径,否则会报 “配置项不存在” 错误。 | |
| streamreadfeature | use_fast_double_parser | 关闭 | 开启 | 解析浮点数字段时使用更快的双精度解析器(基于 jdk.incubator.vector 或优化算法);提升浮点数解析性能,但极端场景下可能存在精度差异(概率极低),需校验高精度浮点数据的解析结果。 |
| use_fast_big_number_parser | 关闭 | 开启 | 解析大数字(如 bigdecimal/biginteger)时使用优化解析器;提升大数字解析效率,无兼容性风险,但需确保解析后的大数精度符合业务要求。 | |
| streamwritefeature | use_fast_double_writer | 关闭 | 开启 | 序列化浮点数时使用更快的双精度写入器;提升浮点数字段序列化性能,极端场景可能存在小数位输出格式差异(如 0.1 变为 0.100000001),需校验金融 / 高精度场景的浮点输出。 |
| tokenstreamfactory.feature | intern_property_names | 启用 | 关闭 | 不再对 json 属性名进行字符串驻留(string intern);减少内存占用(避免常量池膨胀),但频繁解析相同属性名的 json 时,会增加字符串创建开销,高并发场景可按需重新开启。 |
| mapperfeature | use_std_bean_naming | 关闭 | 移除(始终启用) | 强制使用标准 javabean 命名规范(如 getxxx() 对应字段 xxx);2.x 需手动开启,3.x 内置生效,若代码依赖非标准命名(如 getxxx() 对应 xxx),会导致字段序列化 / 反序列化失败。 |
| auto_detect_xxx(creators/fields/getters/is_getters/setters) | 开启 | 移除 | 不再自动检测 bean 的创建器 / 字段 / 访问器,需显式配置可见性规则;2.x 依赖自动检测的场景(如无注解的私有字段序列化)会失效,需通过 changedefaultvisibility 配置字段 / 方法的可见性。 | |
| allow_final_fields_as_mutators | 启用 | 关闭 | 禁止通过反射修改 final 字段的值;2.x 允许强制修改 final 字段(非规范行为),3.x 禁用后,依赖 “final 字段反序列化赋值” 的代码会报错,需改为通过构造器 / 工厂方法初始化 final 字段。 | |
| default_view_inclusion | 启用 | 关闭 | 未指定 @jsonview 时,不再默认序列化所有字段,仅序列化无 view 注解的字段;若代码依赖 “默认包含所有字段” 的逻辑,需显式配置 mapperfeature.default_view_inclusion=true,或补全 @jsonview 注解。 | |
| use_getters_as_setters | 启用 | 关闭 | 不再将 getxxx() 方法当作 setxxx() 使用(如反序列化集合字段时调用 getter 获取集合后添加元素);2.x 为兼容 jaxb 的非规范行为,3.x 禁用后,需为集合 / 映射字段添加显式的 setter 方法。 | |
| sort_properties_alphabetically | 关闭 | 开启 | 序列化 pojo 时默认按字段名字母排序输出;2.x 按字段定义顺序输出,3.x 改变输出顺序,可能导致依赖字段顺序的签名校验(如 md5 验签)失败,需显式配置 @jsonpropertyorder 固定顺序。 | |
| override_public_access_modifiers | 启用 | 关闭 | 不再覆盖公共字段 / 方法的访问修饰符(如强制访问 public final 方法);2.x 可通过反射突破访问限制,3.x 禁用后,需确保 bean 的字段 / 方法访问权限符合序列化要求(如 public getter)。 | |
| datetimefeature | one_based_months | 关闭 | 开启 | 解析 / 序列化日期时,月份按 “1 基” 处理(1=1 月,12=12 月);2.x 部分场景为 “0 基”(0=1 月),修复了月份解析的反直觉问题,但需校验老数据中 “0 基月份” 的兼容性(如 2025-00-09 会解析失败)。 |
| streamreadconstraints | default_max_depth | 1000 | 500 | json 嵌套解析的最大深度从 1000 降至 500;限制深层嵌套 json 的解析,防止栈溢出攻击,但解析超过 500 层的嵌套 json 时会抛出 streamconstraintsexception,需调整超大嵌套 json 的解析限制。 |
| streamwriteconstraints | default_max_depth | 1000 | 500 | json 嵌套序列化的最大深度从 1000 降至 500;序列化深层嵌套对象(如递归引用的对象)时会提前终止,需优化对象结构,或通过 streamwriteconstraints.builder().maxdepth(1000) 调整限制。 |
4. 功能拆分与迁移
- 流式 api 特性拆分: jsonparser.feature → streamreadfeature(通用)+ jsonreadfeature(json 专用); jsongenerator.feature → streamwritefeature + jsonwritefeature(其他格式如 xml/yaml 同理)。
- 迁移配置:
| 属性/方法 | 原位置 | 迁移位置 |
|---|---|---|
| adjust_dates_to_context_time_zone | deserializationfeature | datetimefeature |
| read_date_timestamps_as_nanoseconds | deserializationfeature | datetimefeature |
| fail_on_numbers_for_enums | deserializationfeature | enumfeature |
| read_enums_using_to_string | deserializationfeature | enumfeature |
| read_unknown_enum_values_as_null | deserializationfeature | enumfeature |
| read_unknown_enum_values_using_default_value | deserializationfeature | enumfeature |
| write_dates_as_timestamps | serializationfeature | datetimefeature |
| write_date_keys_as_timestamps | serializationfeature | datetimefeature |
| write_date_timestamps_as_nanoseconds | serializationfeature | datetimefeature |
| write_dates_with_context_time_zone | serializationfeature | datetimefeature |
| write_durations_as_timestamps | serializationfeature | datetimefeature |
| write_dates_with_zone_id | serializationfeature | datetimefeature |
| write_enums_using_to_string | serializationfeature | enumfeature |
| write_enums_using_index | serializationfeature | enumfeature |
| write_enum_keys_using_index | serializationfeature | enumfeature |
| createcontextual() | contextualdeserializer | valuedeserializer |
| createcontextual() | contextualserializer | valueserializer |
| resolve() | resolvabledeserializer | valuedeserializer |
| resolve() | resolvableserializer | valueserializer |
三、注意事项(避坑关键)
1. 依赖管理建议
优先使用 jackson-bom 统一版本(避免 jackson-annotations 版本冲突):
<dependencymanagement>
<dependencies>
<dependency>
<groupid>tools.jackson</groupid>
<artifactid>jackson-bom</artifactid>
<version>3.0.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencymanagement>无需手动引入 jackson-core 和 jackson-annotations,jackson-databind 会自动传递依赖。
2. 代码改造注意
objectmapper 构建: 必须用 builder 模式,示例:
// 3.x 正确写法
jsonmapper mapper = jsonmapper.builder()
.enable(jsonwritefeature.escape_non_ascii)
.changedefaultpropertyinclusion(incl -> incl.withvalueinclusion(jsoninclude.include.non_null))
.build();
// 重新配置已有 mapper(不可变对象无法直接修改)
jsonmapper newmapper = mapper.rebuild()
.enable(serializationfeature.indent_output)
.build();
泛型类型校验: laissezfairesubtypevalidator 不再公开,需用 basicpolymorphictypevalidator 构建:
basicpolymorphictypevalidator validator = basicpolymorphictypevalidator.builder()
.allowifsubtype("com.example")
.build();
日期格式/时区配置: utc 的默认形式现在尾部是 z ,而不是像 2.x 版本中的 +00 。
//错误的方式
mapper.setdateformat(new simpledateformat("yyyy-mm-dd't'hh:mm:ssz"));
mapper.settimezone(timezone.getdefault());
//正确的方式
objectmapper mapper = jsonmapper.builder()
.defaultdateformat(new simpledateformat("yyyy-mm-dd't'hh:mm:ssz"))
.defaulttimezone(timezone.getdefault())
.build();
序列化配置:
//错误的方式 mapper.setserializationinclusion(jsoninclude.include.non_null); //正确的方式 objectmapper mapper = jsonmapper.builder() .changedefaultpropertyinclusion(incl -> incl.withvalueinclusion(jsoninclude.include.non_null)) .changedefaultpropertyinclusion(incl -> incl.withcontentinclusion(jsoninclude.include.non_null)) .build();
可见性配置: mapperfeature.auto_detect_xxx 已移除,需通过 changedefaultvisibility 配置:
//错误的方式
mapper.disable(mapperfeature.auto_detect_fields);
//正确的方式
objectmapper mapper = jsonmapper.builder()
.changedefaultvisibility(vc ->
vc.withfieldvisibility(jsonautodetect.visibility.none))
.build();
包含类型信息配置:
//错误的方式
mapper.activatedefaulttypingasproperty(laissezfairesubtypevalidator.instance,
objectmapper.defaulttyping.non_concrete_and_arrays,
"@class");
//正确的方式
var typevalidator = basicpolymorphictypevalidator.builder()
.allowifsubtype("my.package.base.name.")
.allowifsubtype("java.util.concurrent.")
.allowifsubtypeisarray()
// ...
.build();
objectmapper mapper = jsonmapper.builder()
.activatedefaulttypingasproperty(typevalidator, defaulttyping.non_concrete_and_arrays, "@class")
.build();
jsonnode 处理中的 decimalnode 创建策略 通过 jsonnodefactory 创建 decimalnode 时,旧行为:可能会自动截断尾随零(如 1.200 → 1.2)新行为:默认不截断尾随零,保持最小限度修剪
// 示例:不同的表示方式
bigdecimal value1 = new bigdecimal("1.200"); // 三位小数
bigdecimal value2 = new bigdecimal("1.2"); // 一位小数
// 新行为:decimalnode会保持原始精度
// value1 仍会表示为 "1.200"
// value2 仍会表示为 "1.2"
month 序列化/反序列化行为变更
// java.time.month 枚举
public enum month {
january, // 1
february, // 2
// ...
december // 12
}
// jackson 2.x 序列化结果(默认)
{"month": "january"} // 或使用索引:{"month": 0}
// jackson 3.x 序列化结果(默认)
{"month": 1} // 直接使用 month 的数值(1-12)
3. 性能优化点
关闭末尾字符校验: 若输入数据可信,可禁用 fail_on_trailing_tokens 减少开销:
jsonmapper.builder().disable(deserializationfeature.fail_on_trailing_tokens).build();
缓冲区回收配置: 3.x 默认使用双端队列回收池,高并发场景可切换回 2.x 的 threadlocal 池:
jsonfactory factory = jsonfactory.builder() .recyclerpool(jsonrecyclerpools.threadlocalpool()) .build(); jsonmapper mapper = jsonmapper.builder(factory).build();
4. 兼容性适配
- 若需保留 2.x 部分默认行为,可使用 jsonmapper.builderwithjackson2defaults() 快速迁移(但无法覆盖所有配置)。
- 单元测试需重点检查:字段序列化顺序、日期格式、未知字段处理、枚举序列化方式等受默认配置变更影响的场景。
5. 生态支持
- spring 已在 2025.10 版本支持 jackson 3.x(需升级 spring 相关依赖)。
- 可使用 openrewrite 工具自动完成部分迁移(参考:docs.openrewrite.org/recipes/jav…
总结
jackson 3.x 迁移的核心是 “环境升级 + 依赖变更 + builder 模式适配 + 废弃 api 替换”,关键在于处理包名、不可变对象构建和默认配置变更带来的兼容性问题。建议先升级 jdk 17,再通过依赖替换、代码批量改造(重点是 objectmapper 构建和异常处理)、单元测试验证逐步完成迁移,优先使用官方提供的 builder 方法和兼容工具减少手动改造成本。
到此这篇关于jackson3迁移核心注意点总结大全的文章就介绍到这了,更多相关jackson3迁移注意点内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论