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],作者:[听雨],转载请注明出处。

相关推荐
Hello.Reader5 小时前
一文通关 Proto3语法 + 风格的实战指南
java·开发语言·数据库
Jiezcode5 小时前
Qt QJsonObject
c++·后端·qt
没有bug.的程序员5 小时前
Redis 数据结构全面解析:从底层编码到实战应用
java·数据结构·redis·wpf
IT周小白5 小时前
Apache PDFBox 与 spire.pdf for java 使用记录
java·pdf
文心快码BaiduComate5 小时前
AI界的“超能力”MCP,到底是个啥?
前端·后端·程序员
bobz9655 小时前
华为防火墙支持配置 IPSec 先分片后加密的功能
后端
小蒜学长5 小时前
大学园区二手书交易平台(代码+数据库+LW)
java·数据库·spring boot·后端
saberc86 小时前
【vibe coding系列】0行代码编写,使用Go+Vue3+Flutter从0到1开发小绿书(一)
后端·go
邂逅星河浪漫6 小时前
【机器学习】HanLP+Weka+Java=Random Forest算法模型
java·spring boot·机器学习·weka·random forest