FastJSON解析异常踩坑记录:一个让人头疼的JSON转换问题

前言

最近在开发电子签名项目时遇到了一个特别头疼的问题,系统在处理JSON数据时突然报错,错误信息看起来很奇怪:syntax error : f。经过一番排查,发现是FastJSON在处理特定数据时的一个坑。今天把这个问题记录下来,希望能帮到遇到类似问题的朋友。

问题现象

系统运行得好好的,突然就报错了:

css 复制代码
com.alibaba.fastjson2.JSONException: syntax error : f
at com.alibaba.fastjson2.JSONReaderUTF16.readBoolValue(JSONReaderUTF16.java:6426)
at com.alibaba.fastjson2.JSONReader.read(JSONReader.java:2164)
at com.alibaba.fastjson2.JSON.parse(JSON.java:67)
at com.alibaba.fastjson2.JSON.toJSON(JSON.java:3506)

看到这个错误,第一反应是:什么鬼?JSON格式没问题啊,怎么就解析不了了?

问题代码

出问题的代码很简单,就是想从返回的数据中提取一个字段:

java 复制代码
// 这行代码出问题了
com.alibaba.fastjson2.JSONObject contentJson = 
    (com.alibaba.fastjson2.JSONObject) com.alibaba.fastjson2.JSON.toJSON(invoke.getData().getContent());

String edocId = null;
edocId = contentJson.getString("formRecordId");

if (StringUtils.isBlank(edocId)) {
    edocId = contentJson.getString("formRecordCode");
}

数据分析

接口返回的JSON数据看起来完全正常:

json 复制代码
{
    "id": 8745074954268373736,
    "startAccountId": -8901286526055593580,
    "generateType": null,
    "prevNodeId": 175688901899730,
    "formRecordId": 6003933439012269528,
    "pcPageParam": null,
    "dealTime": 0,
    "nodeName": "管理员",
    "formRecordCode": "6003933439012269528",
    "extLong1": 0,
    "overdueWorkingShow": null
}

乍一看没什么问题,但仔细观察会发现,formRecordId 的值是一个很大的数字:6003933439012269528

问题根源

经过反复测试和分析,发现问题出在FastJSON处理大数字时的一个坑:

  1. 大数字处理问题:当JSON中包含超出JavaScript安全整数范围的数字时,FastJSON在某些情况下会出现解析异常
  2. 类型转换问题 :直接使用 JSON.toJSON() 方法可能会触发内部的类型推断机制,导致解析错误
  3. 字符编码问题:在某些环境下,字符编码也可能影响JSON解析

解决方案

方案一:避免使用 JSON.toJSON()

最直接的解决方法就是改变JSON处理方式:

java 复制代码
// 原来的写法(有问题)
com.alibaba.fastjson2.JSONObject contentJson = 
    (com.alibaba.fastjson2.JSONObject) com.alibaba.fastjson2.JSON.toJSON(invoke.getData().getContent());

// 改进后的写法
String contentStr = com.seeyon.boot.util.JsonUtils.toJson(invoke.getData().getContent());
com.alibaba.fastjson2.JSONObject contentJson = com.alibaba.fastjson2.JSON.parseObject(contentStr);

方案二:统一使用Hutool工具类

既然FastJSON容易踩坑,不如换个更稳定的工具:

java 复制代码
// 使用Hutool的JSON工具
cn.hutool.json.JSONObject contentJson = new cn.hutool.json.JSONObject(invoke.getData().getContent());
String edocId = contentJson.getStr("formRecordId");
if (StrUtil.isBlank(edocId)) {
    edocId = contentJson.getStr("formRecordCode");
}

方案三:增加异常处理

无论用什么方案,都要加上异常处理,让程序更健壮:

java 复制代码
private String invokeGetEdocIdByAffairId(Long affairId) {
    // ... 前面的代码省略
    
    try {
        // 使用更安全的JSON处理方式
        String contentStr = JsonUtil.toJsonStr(invoke.getData().getContent());
        cn.hutool.json.JSONObject contentJson = JSONUtil.parseObj(contentStr);
        
        String edocId = contentJson.getStr("formRecordId");
        if (StrUtil.isBlank(edocId)) {
            edocId = contentJson.getStr("formRecordCode");
        }
        
        log.info("成功提取edocId: {}", edocId);
        return edocId;
        
    } catch (Exception e) {
        log.error("解析JSON数据失败,原始数据: {}", 
                 invoke.getData().getContent(), e);
        return null;
    }
}

为什么选择Hutool?

  1. 稳定性更好:Hutool的JSON工具经过了大量实际项目的验证,对各种边界情况处理得更好
  2. API更友好getStr() 方法比 getString() 更安全,不会因为类型问题抛异常
  3. 性能不错:虽然不是最快的,但在大多数场景下性能完全够用
  4. 维护成本低:API设计简洁,出问题的概率更小

经验总结

  1. 避免直接使用 JSON.toJSON():这个方法在处理复杂对象时容易出问题
  2. 大数字要小心:超出JavaScript安全整数范围的数字可能会导致解析异常
  3. 选择合适的工具:FastJSON虽然性能好,但在某些场景下不如Hutool稳定
  4. 异常处理很重要:JSON解析一定要加try-catch,并记录详细的错误信息
  5. 测试要充分:要用各种边界数据进行测试,不能只测试正常情况

结语

这次踩坑让我深刻体会到,选择技术工具不能只看性能,稳定性和易用性同样重要。FastJSON在高并发场景下确实性能不错,但对于业务代码来说,稳定性更重要。

希望这篇文章能帮助到遇到类似问题的朋友。如果你也遇到过类似的JSON解析问题,欢迎在评论区分享你的解决方案!


本文档基于实际项目开发中遇到的问题总结而成,如有疑问欢迎交流讨论。

本文首发于[掘金/CSDN],作者:[听雨],转载请注明出处。

相关推荐
东东5161 天前
学院个人信息管理系统 (springboot+vue)
vue.js·spring boot·后端·个人开发·毕设
一个响当当的名号1 天前
lectrue9 索引并发控制
java·开发语言·数据库
进阶小白猿1 天前
Java技术八股学习Day30
java·开发语言·学习
三水不滴1 天前
Redis缓存更新策略
数据库·经验分享·redis·笔记·后端·缓存
hhy_smile1 天前
Class in Python
java·前端·python
小邓吖1 天前
自己做了一个工具网站
前端·分布式·后端·中间件·架构·golang
qq_12498707531 天前
基于Srpingboot心晴疗愈社平台的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·spring·microsoft·毕业设计·计算机毕业设计
大爱编程♡1 天前
SpringBoot统一功能处理
java·spring boot·后端
leiming61 天前
FreeRTOS 的任务与 Linux
java·开发语言
小马爱记录1 天前
枚举策略驱动
java