当前位置: 首页 > news >正文

【Bug经验分享】由jsonObject-TypeReference引发的序列化问题

报错

fastjson.JSONException: syntax error, expect {, actual string

背景

InnerResult<Map<Long, Price>> categoryAttributeRequiredSPMResp = JsonUtil.convertJSONString2Object(res, new TypeReference<InnerResult<Map<Long, Price>>>() { });

在这段代码中会出现反序列化 "异常",转换不了Price对象,在之前的测试中一直都是这种方式使用的,也可以转换为Price对象但是,突然在某一天生产上抛出了异常,定位后发现是在这里出现了类型转换异常,复杂对象序列化为json字符串之后,反序列化的时候异常,明明类型是对的,但是就是转换失败,详细代码如下:

public Map<Long, Price> listPriceByIds(List<Long> productIds) {if (CollectionUtils.isEmpty(productIds)) {return new HashMap<>();}String url = spmUrl + "/supplier-product-self-built-product/purchase-price";try {String res = HttpUtils.postBody(url, "json", JSON.toJSONString(productIds));logger.info("获取SPM采购价格,traceId={},请求地址={},请求参数={},响应={}", SwapAreaUtils.getSwapArea().get(Constant.TRACE_KEY), url, JSON.toJSONString(productIds), res);InnerResult<Map<Long, Price>> categoryAttributeRequiredSPMResp = JsonUtil.convertJSONString2Object(res, new TypeReference<InnerResult<Map<Long, Price>>>() {});if (!categoryAttributeRequiredSPMResp.getCode().equals(0)) {return new HashMap<>();}return categoryAttributeRequiredSPMResp.getData();} catch (Exception e) {logger.error("获取SPM采购价格,traceId={},请求地址={},请求参数={}", SwapAreaUtils.getSwapArea().get(Constant.TRACE_KEY), url, JSON.toJSONString(productIds));logger.error("获取SPM采购价格接口失败", e);return new HashMap<>();}
}
/*** 将json串转换为类型为className的对象.* 处理如下json:{'field1':1,'field2':'a'}** @param <T>        类型参数* @param jsonString json字符串* @param type       TypeReference<T>* @return 对象*/
public static <T> T convertJSONString2Object(String jsonString, TypeReference<T> type) {return JSON.parseObject(jsonString, type);
}

修复

public Map<Long, Price> listPriceByIds(List<Long> productIds) {if (CollectionUtils.isEmpty(productIds)) {return new HashMap<>();}String url = spmUrl + "/supplier-product-self-built-product/purchase-price";try {String res = HttpUtils.postBody(url, "json", JSON.toJSONString(productIds));logger.info("获取SPM采购价格,traceId={},请求地址={},请求参数={},响应={}", SwapAreaUtils.getSwapArea().get(Constant.TRACE_KEY), url, JSON.toJSONString(productIds), res);InnerResult<JSONObject> innerResult = JsonUtil.convertJSONString2Object(res, new TypeReference<InnerResult<JSONObject>>() {});if (!innerResult.getCode().equals(0)) {return new HashMap<>();}Map<Long, Price> resultMap = new HashMap<>();for (Map.Entry<String, Object> entry : innerResult.getData().entrySet()) {Price price = JSON.parseObject(JSON.toJSONString(entry.getValue()), Price.class);if (price != null) {resultMap.put(Long.valueOf(entry.getKey()), price);}}return resultMap;} catch (Exception e) {logger.error("获取SPM采购价格,traceId={},请求地址={},请求参数={}", SwapAreaUtils.getSwapArea().get(Constant.TRACE_KEY), url, JSON.toJSONString(productIds));logger.error("获取SPM采购价格接口失败", e);return new HashMap<>();}
}

主要是先将返回值转为 JSONObject 对象,其次取出key,value后自行组装Map这样是稳妥解决了这个类型转换的异常



反思


在定位这个问题的时候,就从来没想过这边会出现问题,因为代码是完全没有动过的,理论上不会有问题,打日志定位后 发现 但是 很鬼畜的事情就是突然发生 类型转换异常,那为什么之前从来没出现过这个问题,怀疑是 alibaba.fastjson 这个包下的TypeReference 序列化 多多少少是有Bug的,不知道是不是版本不稳定引起的--  后面再看看吧

http://www.xdnf.cn/news/1285093.html

相关文章:

  • 无人机在环保监测中的应用:低空经济发展的智能监测与高效治理
  • 从0开始的中后台管理系统-5(菜单的路径绑定以及角色页面的实现)
  • Javase 之 字符串String类
  • 《飞算Java AI:从安装到需求转实战项目详细教学》
  • 机器学习算法篇(十):TF-IDF算法详解与应用实战
  • 线性代数 · 矩阵 | 最小多项式
  • IoTDB与传统数据库的核心区别
  • Spring Boot项目使用WebClient调用第三方接口详细教程
  • Elasticsearch Node.js 客户端连接指南(Connecting)
  • 一起来聊聊GPT-5
  • 面试经典150题[001]:合并两个有序数组(LeetCode 88)
  • 从零开始手搓一个GPT大语言模型:从理论到实践的完整指南(一)
  • 安全合规5--终端安全检测和防御技术
  • MySQL基础面试
  • MySQL 索引优化实战:从执行计划分析到优化策略落地
  • 【狂热算法篇】探寻图论幽径之SPFA算法:图论迷宫里的闪电寻径者(通俗易懂版)
  • 【Unity笔记】视频播放控制器全攻略:支持延迟播放、事件回调与多视频管理的完整实现
  • 数据结构:图
  • 【力扣494】目标和
  • 【代码随想录day 17】 力扣 98.验证二叉搜索树
  • 网站测评-利用缓存机制实现XSS的分步测试方法
  • 正向传播与反向传播(神经网络思维的逻辑回归)
  • 动态规划----1.爬楼梯
  • VUE的8个生命周期
  • 将黑客拒之物联网网络之外的竞赛
  • Openlayers基础教程|从前端框架到GIS开发系列课程(24)openlayers结合canva绘制矩形绘制线
  • Etcd客户端工具Etcd Workbench更新了1.2.0版本!多语言支持了中文,新增了许多快捷功能使用体验再次提升
  • Linux中Apache与Web之虚拟主机配置指南
  • 【门诊进销存出入库管理系统】佳易王医疗器械零售进销存软件:门诊进销存怎么操作?系统实操教程 #医药系统进销存
  • sqli-labs通关笔记-第44关 POST字符型堆叠注入(单引号闭合 手工注入+脚本注入3种方法)