Fastjson 序列化报 ArrayIndexOutOfBoundsException?前端 + 后端联合排查与解决
问题背景
最近在使用 Fastjson(版本 1.1.38)序列化对象时,遇到了java.lang.ArrayIndexOutOfBoundsException: 160
异常,堆栈指向SerializeWriter.writeFieldValueStringWithDoubleQuote
方法。初步怀疑是对象 “长度太长”,但深入分析后发现,问题根源与 Fastjson 旧版本的序列化逻辑缺陷、前端 URL 参数未正确编码密切相关。本文结合权威资料与实践经验,总结完整排查思路与解决方案。
异常核心原因分析
异常本质是 Fastjson 内部字符缓冲区溢出。Fastjson 1.1.38 作为 2014 年的极旧版本,其SerializeWriter
类在处理字符串序列化时,使用固定大小的字符数组(如默认 1024)作为缓冲区。当遇到以下场景时,缓冲区索引会越界:
1. 后端:Fastjson 旧版本的序列化缺陷
- 特殊字符未处理:若对象字段包含控制字符(如
\u0000
空字符)、未转义的\
或"
,Fastjson 旧版本无法正确计算缓冲区写入位置,导致索引越界。 - 复杂对象结构:嵌套对象、数组或集合的递归序列化可能触发索引计算错误(如数组长度未校验)。
2. 前端:URL 参数未编码传递
前端传递参数时,若 URL 中包含特殊字符(如&
、空格、中文)未用encodeURIComponent
编码,后端接收参数时可能因解析错误(如&
被识别为参数分隔符),导致字段值不完整或格式错误,间接触发 Fastjson 序列化异常。
多维度解决方案(前端 + 后端)
方案 1:前端对 URL 参数编码(关键预防)
前端传递参数前,需用encodeURIComponent
对参数值编码,将特殊字符转换为%XX
形式(如空格→%20
,&
→%26
),避免后端解析错误。
示例(JavaScript):
javascript
// 前端传递参数时编码
const paramValue = "测试&特殊字符 空格#";
const encodedValue = encodeURIComponent(paramValue);
// 编码结果:"测试%26特殊字符%20空格%23"
const url = `http://api.example.com/query?param=${encodedValue}`;
方案 2:后端升级 Fastjson 版本(最有效)
Fastjson 1.2.6 + 版本优化了SerializeWriter
的动态扩容逻辑(自动根据内容调整缓冲区大小),2.0.x 版本彻底重构序列化引擎,修复了缓冲区溢出问题。
Maven 依赖(推荐):
xml
<!-- 1.x稳定版(兼容旧代码) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<!-- 2.x新版(性能更优) -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.25</version>
</dependency>
方案 3:清理或转义特殊字符(兼容旧版本)
若无法升级 Fastjson,需检查对象字段是否包含特殊字符(如控制字符\u0000-\u001F
),序列化前清理或转义。
示例(Java):
java
public class TBean {
private String content;
// 清理控制字符(保留可打印字符)
public String getCleanContent() {
if (content == null) return null;
return content.replaceAll("[\\u0000-\\u001F]", "");
}
}
// 序列化时使用清理后的字段
String json = JSON.toJSONString(tBean.getCleanContent());
方案 4:调整序列化配置(辅助手段)
通过SerializerFeature
调整序列化行为,减少缓冲区压力:
java
// 禁用循环引用检测(降低递归复杂度),强制非字符串值转字符串
String json = JSON.toJSONString(tBean,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteNonStringValueAsString
);
方案 5:替换为其他 JSON 库(终极备选)
若 Fastjson 问题仍无法解决,可替换为 Jackson 或 Gson(对复杂对象和特殊字符兼容性更好)。
Jackson 示例:
java
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(tBean); // 直接序列化对象
总结
ArrayIndexOutOfBoundsException
的核心是 Fastjson 1.1.38 的序列化缓冲区缺陷,前端 URL 未编码可能触发或加剧此问题。
最优组合方案:前端用encodeURIComponent
编码参数 + 后端升级 Fastjson 到 1.2.83+/2.0.25+,可 99% 以上避免此类异常。若需兼容旧环境,需结合字段清理或替换 JSON 库。
更多推荐
所有评论(0)