近期发现公司同事在使用Gson对数字进行反序列列化时出现丢失精度的问题,在这里搬运一下,做个记录~
现象
使用Gson反序列化长Long数字(大于16位),如果用Object类型来接收则会丢失精度。
Gson会将数字反序列化为double类型,double类型本身就容易丢精度。(精度丢失原因可自行搜索)
再转回Long时就会导致数据异常
根因
Gson在把数字反序列为Object时,默认会转换成Double。
可以看Gson的ObjectTypeAdapter类
碰到数字类型时,会调用toNumberStrategy。
如果你的Gson低于2.8.9,这里就不会使用toNumberStrategy。
直接是in.nextDouble();
这个toNumberStrategy是构建Gson对象时传入的,在Gson2.8.9中默认是Double策略
所以,Gson在把数字反序列为Object时,默认会转换成Double。
而超过16位的数字转成Double,精度就会丢失导致数据不正确。
解决办法
1.尽量避免用Object来接收大数字,最好使用字符串String接收
2.如果你非要用Object。那就修改Gson反序列化Object时候的策各吧(需要Gson版本>=2.8.9)
在GsonBuilder中有一个方法setObjectToNumberStrategy(),建议改成BigDecimal策略一劳永逸。