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

GSON转换将Long类型转换Double导致精度丢失的问题排查

问题描述

项目中同步订单时发现一个问题,同一条的数据,order_id和item_id为Long类型,在同步时,数值变了。比如原本是6930414387088791188变成了69304143870884512001。

问题排查

经过排查发现http请求的返回参数是正常的,问题出现在客户端调用接口得到结果后,在进行json转换时,出现问题。项目中使用的gson作为json序列化和反序列化的工具。
转换代码如下:

Result result = JsonUtil.jsonToObject(httpResult.getBody(), Result.class);
List<OrderResponse> list =JsonUtil.jsonToList(JsonUtil.objectToJson(result), OrderResponse.class);

这个转换,第一步会使用gson默认的object转换:将数值类型转换成了Double类型。第二步再转换为指定类型时,数值就变了。
查看源码发现,只要是源数据是数值类型,在不指定类型的情况进行转换时,会使用gson默认的转换ObjectTypeAdapter,将所有数值型转换为Double,当源数据的Long型长度为19位(超过16位),丢失了精度,导致数据发生了变化。
在这里插入图片描述

解决方案

  1. **(推荐)**转换时制定好类型,不用gson默认的转换。转换方法如下:
    返回类定义如下:
public class ResponseList<T> {private String code;//状态码private String msg;//处理消息private List<T> data;...
}

JsonUtil中转换方法如下:

public static <T> T fromJson(String json, Class<T> clazz, Class type) {if (StringUtils.isBlank(json)) {return null;}Type objectType = type(clazz, type);return gson.fromJson(json, objectType);
}private static ParameterizedType type(final Class raw, final Type... args) {return new ParameterizedType() {public Type getRawType() {return raw;}public Type[] getActualTypeArguments() {return args;}public Type getOwnerType() {return null;}};
}

调用http结果后json转实体如下:

ResponseList<OrderResponse> resultResponse = JsonUtil.fromJson(httpResult.getBody(), ResponseList.class, OrderResponse.class);
  1. 如果继续想使用gson默认的转换,升级gson版本>=2.8.9,设置默认的转换策略,用BigDecimal接收,亲测可用
    升级gson版本至2.8.9以上
 <dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.9</version>
</dependency>
public class JsonUtil {private static Gson gson = new Gson();static {GsonBuilder gsonBuilder = new GsonBuilder();gsonBuilder.setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL);gson = gsonBuilder.create();}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Redis:查询是否包含某个字符/字符串之二
  • STM32-外部中断-AFIO-串口-串口通信-串口中断(空闲中断和接收中断)-printf移植-ADC数模转换-初始化和读取光敏电阻AO
  • Unity 使用 NewtonSoft Json插件报错
  • 基于华为的LTC流程体系,建立销售营销指标体系的探讨
  • YoloV8改进策略:Block改进|自研GroupxLSTM模块|即插即用(顶会专属)
  • react多级权限路由
  • 【云原生】Pass容器研发基础——汇总篇
  • 集合-List去重
  • jquery div触发粘贴事件
  • Linux驱动入门实验班——Hello驱动(后附百问网课程视频链接)
  • ARM CoreLink 系列 5.1.1 -- CI-700 System Address Map 】
  • 全开源智慧停车场微信小程序源码/智能停车系统源码/停车自助缴费系统/停车场管理收费+物业管理+物联网+自助缴费功能
  • MySQL- 索引下推
  • C++ 知识点(长期更新)
  • 分布式版本控制概述
  • 深入了解以太坊
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • [Vue CLI 3] 配置解析之 css.extract
  • create-react-app做的留言板
  • E-HPC支持多队列管理和自动伸缩
  • Javascript弹出层-初探
  • node和express搭建代理服务器(源码)
  • text-decoration与color属性
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • vue:响应原理
  • vue脚手架vue-cli
  • Vue学习第二天
  • webpack项目中使用grunt监听文件变动自动打包编译
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 翻译:Hystrix - How To Use
  • 诡异!React stopPropagation失灵
  • 看域名解析域名安全对SEO的影响
  • 前端性能优化——回流与重绘
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 移动端解决方案学习记录
  • 由插件封装引出的一丢丢思考
  • zabbix3.2监控linux磁盘IO
  • 阿里云服务器如何修改远程端口?
  • ​你们这样子,耽误我的工作进度怎么办?
  • ######## golang各章节终篇索引 ########
  • $.proxy和$.extend
  • %check_box% in rails :coditions={:has_many , :through}
  • (1)bark-ml
  • (2)nginx 安装、启停
  • (bean配置类的注解开发)学习Spring的第十三天
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (pycharm)安装python库函数Matplotlib步骤
  • (rabbitmq的高级特性)消息可靠性
  • (web自动化测试+python)1
  • (八)Flask之app.route装饰器函数的参数
  • (苍穹外卖)day03菜品管理
  • (差分)胡桃爱原石
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统