1. 为什么选择FastJSON2替代Jackson
Spring Boot默认集成Jackson作为JSON处理器,但在某些场景下FastJSON2可能更具优势。FastJSON2是阿里巴巴开源的JSON处理库,相比Jackson有以下特点:
- 性能优势:FastJSON2在序列化/反序列化速度上比Jackson快30%-50%,特别是在处理大JSON数据时更明显
- 内存占用低:FastJSON2的内存占用比Jackson减少约20%
- 更简洁的API:FastJSON2的API设计更符合中国开发者的使用习惯
- 更好的中文支持:内置对中文日期格式、特殊字符等的处理
注意:FastJSON2需要Spring 6+环境支持,这也是为什么我们要使用
fastjson2-extension-spring6这个扩展包
2. 完整依赖配置详解
2.1 Maven依赖配置
除了基础依赖,建议添加以下优化配置:
<dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.53</version> </dependency> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2-extension-spring6</artifactId> <version>2.0.53</version> </dependency>2.2 Gradle配置
如果使用Gradle构建项目:
implementation 'com.alibaba.fastjson2:fastjson2:2.0.53' implementation 'com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.53'2.3 版本选择策略
- 始终使用最新稳定版(目前2.0.53)
- 避免使用SNAPSHOT版本
- 主版本号升级可能有不兼容变更,需要测试
3. 深度配置FastJSON2消息转换器
3.1 基础配置类实现
@Configuration public class Fastjson2Config implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); FastJsonConfig config = new FastJsonConfig(); config.setDateFormat("yyyy-MM-dd HH:mm:ss"); config.setWriterFeatures( WriteFeature.WriteMapNullValue, WriteFeature.WriteNullListAsEmpty, WriteFeature.WriteNullStringAsEmpty ); converter.setFastJsonConfig(config); converter.setDefaultCharset(StandardCharsets.UTF_8); converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); // 添加到转换器列表首位 converters.add(0, converter); } }3.2 关键配置项说明
- 日期格式:
setDateFormat()设置统一日期格式 - 空值处理:
WriteMapNullValue:序列化时保留null字段WriteNullListAsEmpty:空列表序列化为[]WriteNullStringAsEmpty:空字符串序列化为""
- 字符编码:统一使用UTF-8
- 媒体类型:只处理application/json
3.3 高级配置选项
// 在FastJsonConfig中可添加的额外配置 config.setSerializerFeatures( SerializerFeature.PrettyFormat, // 美化输出 SerializerFeature.WriteClassName // 写入类名 ); // 自定义序列化器 config.setWriterFilters(new ValueFilter() { @Override public Object apply(Object object, String name, Object value) { // 自定义序列化逻辑 return value; } });4. 实际应用场景示例
4.1 Controller层使用
@RestController @RequestMapping("/api") public class UserController { @GetMapping("/user") public User getUser() { // 直接返回对象,由FastJSON2自动序列化 return new User(1, "张三", LocalDateTime.now()); } @PostMapping("/user") public User createUser(@RequestBody User user) { // 自动反序列化请求体 return userService.save(user); } }4.2 自定义序列化/反序列化
// 自定义日期序列化 JSON.register(LocalDateTime.class, (object, format) -> { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分"); return formatter.format(object); }); // 使用TypeReference处理复杂泛型 List<User> users = JSON.parseObject(jsonStr, new TypeReference<List<User>>(){});5. 性能优化与最佳实践
5.1 线程安全配置
FastJSON2的核心对象都是线程安全的,但建议:
FastJsonConfig实例应该单例使用- 避免频繁创建
FastJsonHttpMessageConverter实例 - 复杂对象的
TypeReference应该缓存复用
5.2 缓存策略
// 启用缓存提高性能 FastJsonConfig config = new FastJsonConfig(); config.setReaderFeatures(Feature.SupportAutoType); config.setWriterFeatures(WriteFeature.IgnoreErrorGetter);5.3 与Jackson共存方案
如果需要同时支持FastJSON2和Jackson:
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // FastJSON2转换器 FastJsonHttpMessageConverter fastJsonConverter = createFastJsonConverter(); converters.add(0, fastJsonConverter); // 保留Jackson转换器 converters.add(new MappingJackson2HttpMessageConverter()); }6. 常见问题排查
6.1 日期格式不生效
可能原因:
- 配置类未正确加载 - 检查
@Configuration注解 - 存在多个配置类冲突 - 检查
@Order注解 - 实体类上有
@JsonFormat注解覆盖配置
解决方案:
// 确保实体类不使用Jackson注解 @Data public class User { private LocalDateTime createTime; // 会使用全局配置 }6.2 中文乱码问题
解决方案:
- 确保设置了UTF-8编码
- 检查HTTP响应头Content-Type
- 避免在拦截器中修改响应编码
6.3 循环引用问题
FastJSON2默认检测循环引用,可以通过配置关闭:
config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);或者使用@JSONField(serialize = false)注解忽略特定字段
7. 测试验证方案
7.1 单元测试配置
@SpringBootTest @AutoConfigureMockMvc class Fastjson2Test { @Autowired private MockMvc mockMvc; @Test void testJsonSerialization() throws Exception { mockMvc.perform(get("/api/user")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("张三")) .andDo(print()); } }7.2 性能对比测试
使用JMH进行序列化性能测试:
@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) public class JsonBenchmark { @Benchmark public void fastjson2Serialize() { JSON.toJSONString(testData); } @Benchmark public void jacksonSerialize() throws JsonProcessingException { new ObjectMapper().writeValueAsString(testData); } }8. 生产环境建议
监控指标:
- 序列化/反序列化平均耗时
- JSON处理异常次数
- 内存使用情况
安全配置:
// 关闭自动类型识别防止安全漏洞 config.setReaderFeatures(Feature.SupportAutoType.masked);- 日志记录:
@Slf4j @Configuration public class Fastjson2Config implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 配置完成后记录日志 log.info("FastJSON2配置加载完成,当前版本:{}", JSON.VERSION); } }在实际项目中,我建议将FastJSON2的配置封装成独立的starter,方便多项目复用。同时要注意定期更新FastJSON2版本,修复可能的安全漏洞。对于特别复杂的JSON结构,可以先进行性能测试再决定是否采用FastJSON2。