背景
在将一个 JsonObject 转成 Map<String, Object> 的时候,数字全部被转成了 double 类型,
如下所示,年龄从 2 变成了 2.0,身高正常显示 98.2,登记时间成了 1.694533284627E12
/**
* name=小红
* record_time=1.694533284627E12
* age=2.0
* height=98.2
*/
public static void main(String[] args) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("name", "小红");
jsonObject.addProperty("age", 2);
jsonObject.addProperty("height",98.2);
jsonObject.addProperty("record_time", System.currentTimeMillis());
Map<String, Object> result = new Gson().fromJson(jsonObject, new TypeToken<HashMap<String, Object>>() {
}.getType());
for (Map.Entry entrySet : result.entrySet()){
System.out.println(entrySet.getKey()+"="+entrySet.getValue());
}
}
排查过程
面对搜索引擎编程,我肯定不是第一个踩坑的,果不其然
https://stackoverflow.com/questions/15507997/how-to-prevent-gson-from-expressing-integers-as-floats
从解释中可以看出,gson 默认将 number 类型的数据解析成了 double 类型
case NUMBER:
return in.nextDouble();
并且提到此问题已在版本 2.8.9 中修复
google fixed issue
https://github.com/google/gson/commit/fe30b85224316cabf19f5dd3223843437c297802#diff-9bf510cca1fa5b32b008e7daa417abf15602571dbc87f5436d9f3558ded492a5 please update gson version to 2.8.9
查看自己的版本号为 2.8.6 低于 2.8.9,且也有相同情况
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
解决方案
问题已定位,就比较好解决
首先将 gson 版本升到 2.8.9,然后在创建 gson 对象的时候手动设置数字类型的转换策略,问题解决,如下
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
/**
* name=小红
* record_time=1694534362190
* age=2
* height=98.2
*/
public static void main(String[] args) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("name", "小红");
jsonObject.addProperty("age", 2);
jsonObject.addProperty("height",98.2);
jsonObject.addProperty("record_time", System.currentTimeMillis());
// 手动设置数字类型数据的转换策略
GsonBuilder gson = new GsonBuilder().setNumberToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE);
Map<String, Object> result = gson.create().fromJson(jsonObject, new TypeToken<HashMap<String, Object>>() {
}.getType());
for (Map.Entry entrySet : result.entrySet()){
System.out.println(entrySet.getKey()+"="+entrySet.getValue());
}
}
我不是第一个踩此坑的,肯定也不会是最后一个踩此坑的,简单记录,等待有缘人