从 Fastjson1 迁移到 Fastjson2
为什么需要迁移?
Fastjson2(版本2.x)是 Fastjson1(1.2.x)的完全重写版,主要改进包括:
- 安全性增强:默认禁用危险的反序列化特性,修复了多个高危漏洞
- 性能提升:采用全新解析引擎,序列化/反序列化速度提升30%以上
- API更简洁:废弃已过时方法,提供更直观的调用方式
第一步:替换依赖
Maven配置
<!-- 旧版 Fastjson1 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<!-- 新版 Fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.61</version>
</dependency>
包路径变化:com.alibaba.fastjson → com.alibaba.fastjson2
第二步:核心API迁移对照
1. JSON序列化
Fastjson1写法:
User user = new User("张三", 25);
String json = JSON.toJSONString(user);
Fastjson2写法:
User user = new User("张三", 25);
String json = JSON.toJSONString(user);
// 方法名完全相同,无缝升级
2. JSON反序列化
Fastjson1写法:
String json = "{\"name\":\"李四\",\"age\":30}";
User user = JSON.parseObject(json, User.class);
Fastjson2写法:
String json = "{\"name\":\"李四\",\"age\":30}";
User user = JSON.parseObject(json, User.class);
// 依旧保持兼容,无需修改
3. JSONArray/JSONObject处理
Fastjson1写法:
JSONArray arr = JSON.parseArray("[1,2,3]");
JSONObject obj = JSON.parseObject("{\"key\":\"value\"}");
Fastjson2写法:
// 在 Fastjson2 中,JSONArray/JSONObject 依然存在且可用
// 但为了追求极致性能和类型安全,官方更推荐直接解析为 Java 原生集合(List/Map)或自定义对象。
List<Integer> list = JSON.parseArray("[1,2,3]", Integer.class);
Map<String, Object> map = JSON.parseObject("{\"key\":\"value\"}");
第三步:需要注意的改动
1. 日期格式化
旧写法(可能出问题):
JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd");
新写法(推荐):
// 直接定义日期格式
String json = JSON.toJSONString(user, "yyyy-MM-dd");
// Fastjson2支持全局配置或注解驱动
@Data
public class User {
@JSONField(format = "yyyy-MM-dd")
private Date birthday;
}
2. 过滤/处理字段
旧写法:
SimplePropertyPreFilter filter = new SimplePropertyPreFilter(User.class, "name");
新写法:
- 基础过滤:API 基本兼容,继续使用 SimplePropertyPreFilter 或 PropertyFilter。
// 依然需要传入过滤器对象
SimplePropertyPreFilter filter = new SimplePropertyPreFilter(User.class, "name");
JSON.toJSONString(user, filter);
- 高级脱敏:使用 Fastjson2 新增的 BeforeFilter,可在序列化前拦截并修改字段值(如密码脱敏)。
- 默认行为优化:Fastjson2 默认不输出 null 值和默认值(如 0),无需像 1.x 那样繁琐配置 WriteMapNullValue。
3. 安全性配置
Fastjson2 默认禁用 AutoType,天然防御反序列化漏洞。
- 基础防护(推荐):直接使用 JSON.parseObject(json, User.class),避免使用无类型的 parse 方法。
- 白名单机制(多态场景):如果业务必须支持 @type 字段,务必配置白名单:
ParserConfig config = new ParserConfig();
// 仅允许特定包下的类进行反序列化
config.addAccept("com.example.domain.");
JSON.parseObject(json, Object.class, config);
- 终极防护(SafeMode):如果不需要任何自动类型特性,可开启安全模式彻底禁止 @type:
// 启动参数: -Dfastjson.parser.safeMode=true
// 或代码配置:
ParserConfig.getGlobalInstance().setSafeMode(true);
完整迁移示例
假设我们需要重构一个实体类解析功能:
// 旧代码(Fastjson1)
public class Fastjson1Demo {
public static void main(String[] args) {
String json = "{\"userId\":101,\"userName\":\"admin\",\"createTime\":\"2024-01-15\"}";
// 使用JSONObject
JSONObject obj = JSON.parseObject(json);
long id = obj.getLong("userId");
String name = obj.getString("userName");
// 反序列化为对象
User user = JSON.parseObject(json, User.class);
System.out.println(user);
}
}
// 新代码(Fastjson2)
public class Fastjson2Demo {
public static void main(String[] args) {
String json = "{\"userId\":101,\"userName\":\"admin\",\"createTime\":\"2024-01-15\"}";
// 优先使用Map代替JSONObject
Map<String, Object> map = JSON.parseObject(json);
long id = ((Number)map.get("userId")).longValue();
String name = (String) map.get("userName");
// 反序列化不变
User user = JSON.parseObject(json, User.class);
System.out.println(user);
}
}
// 实体类需要增加时间格式注解
@Data
public class User {
private long userId;
private String userName;
@JSONField(format = "yyyy-MM-dd")
private Date createTime;
}
Fastjson2 迁移检查清单
1. 依赖与包路径
- 更新 Maven/Gradle 坐标
- 移除
com.alibaba:fastjson - 新增
com.alibaba.fastjson2:fastjson2(建议使用最新稳定版)
- 移除
- 全局替换 Import 路径
- 查找替换:
import com.alibaba.fastjson→import com.alibaba.fastjson2 - 注意:如果是 Spring Boot 项目,检查是否引入了
fastjson-http-message-converter的对应 2.x 版本。
- 查找替换:
2. 代码适配 (核心)
- 调整集合反序列化写法
- 旧写法:
JSON.parseObject(json, new TypeReference<List<User>>() {}) - 新写法:
JSON.parseArray(json, User.class)(Fastjson2 简化了泛型处理,优先用这个)
- 旧写法:
- 审查 JSONObejct/JSONArray 的使用
- 修正点:不需要全部改为 List/Map!
- 行动:保留动态字段场景下的使用,但需修改导入包。仅在追求极致性能的核心链路中,才建议重构为 JavaBean 或 Map。
- 修复 Bean 规范
- 重点:Fastjson2 对 Java Bean 规范要求更严。确保实体类有无参构造函数,且字段非
final(除非有特殊配置)。Lombok 用户请确保@Data生效。
- 重点:Fastjson2 对 Java Bean 规范要求更严。确保实体类有无参构造函数,且字段非
3. 安全与配置
- 清理 AutoType 配置
- 删除
ParserConfig.getGlobalInstance().setAutoTypeSupport(true)等全局开启的代码。 - 替代方案:如需多态支持,改用
config.addAccept("com.example.")配置白名单。
- 删除
- 检查日期格式化
- 行为变更:Fastjson2 默认将 Date 序列化为字符串(1.x 默认为时间戳)。
- 行动:如果前端依赖时间戳,需添加
@JSONField(format = "millis")或全局配置。如果只需普通日期,确认格式是否符合预期(如yyyy-MM-dd HH:mm:ss)。
4. 验证与测试
- 运行全量单元测试
- 重点关注:空对象
{}、Null 值字段、嵌套过深的 JSON。
- 重点关注:空对象
- 对比输出结果
- 检查序列化后的 JSON 字符串是否与 1.x 完全一致(特别是 Null 字段的处理,2.x 默认不输出 Null)。
总结: Fastjson2并非完全兼容旧版本,但核心API改动极小。只要注意 JSONObject/JSONArray 和安全性配置,大多数项目可在1小时内完成迁移。建议先在测试环境验证,再推广到生产系统。

