29 May 2022

将 Fastjson 1.x 迁移到 Fastjson2 时,我把两件事分开处理:Spring MVC 接口统一使用 Jackson,仍需 JSON 工具能力的内部代码再迁移到 Fastjson2。这样可以分别验证接口协议与工具调用,减少一次改动影响的范围。

先分清原生包与兼容方案

Fastjson2 原生 API 使用 com.alibaba.fastjson2 包名;迁移时需要同时检查依赖坐标、import 和特性配置,不能只替换一个版本号。兼容模块与原生模块的行为也应分别验证。

这次迁移使用过 2.0.4,属于当时的环境记录,不是后续项目的版本选型建议。实际项目应采用经过依赖管理和验证的目标版本。

import com.alibaba.fastjson2.JSON;

String json = JSON.toJSONString(value);
MyBean bean = JSON.parseObject(json, MyBean.class);

这只是调用形式。空值输出、字段命名、日期、枚举、大整数、重复引用和多态类型都可能影响结果,需要按实际目标版本与原接口对照。

Spring MVC 的输出单独验证

移除自定义 Fastjson 消息转换器后,应确认运行时实际注册的转换器、JSON 注解和 ObjectMapper 配置。不要因为项目引入了 Jackson,就认定所有接口已经切换。

旧项目中使用 Date 时,可以配置:

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.locale=zh
spring.jackson.time-zone=GMT+8

这里是小写 yyyy,大写 YYYY 表示基于周的年份,在年末年初可能产生不同结果。LocalDate、LocalDateTime 等 Java 时间类型要结合 JavaTimeModule 或字段格式单独检查,不能假定这三个配置覆盖所有日期类型。

避免用全局关闭检查来掩盖实体输出问题

Hibernate 代理对象、双向关联和会话关闭后的懒加载,都可能影响序列化。接口优先返回明确的 DTO,而不是直接暴露完整实体图。

忽略 hibernateLazyInitializer、handler 可以处理特定代理属性,但不等于解决关联取数和循环引用。全局关闭 FAIL_ON_EMPTY_BEANS 还可能让本该暴露的问题变成空对象。自行 new ObjectMapper() 也可能丢掉 Spring Boot 已注册的模块与配置,不宜作为通用修复。

用协议样例确认迁移结果

保留一组接口输入输出样例,重点检查 null 与缺失字段、超出 JavaScript 安全整数范围的 ID、日期时区、中文、枚举和嵌套对象。既验证序列化,也验证反序列化及失败输入的处理。

迁移的目标是让业务协议可控,不是让两套库在所有情况下碰巧输出相同文本。确实需要保留的差异,应在接口约定和测试中说明。

参考:Fastjson 1.x 升级说明。





blog comments powered by Disqus
Fork me on GitHub