Gson int类型被转换成double问题解决
一、问题复现
1.1、方法封装
/**
* 获取list
*
* @param json 数据源
* @param type TypeToken.getParameterized(List.class, xxx.class).getType();
*/
public static List<?> fromJson(String json, Type type) {
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
return gson.fromJson(json, type);
}
1.2、数据演示
public static void main(String[] args) {
String data = "[{\"id\":37,\"parentId\":0,\"name\":\"首页\",\"data\":{\"menuUrl\":\"/\",\"menuCode\":\"0001\"},\"children\":[],\"leaf\":true},{\"id\":38,\"parentId\":0,\"name\":\"书籍\",\"data\":{\"menuUrl\":\"/grid.html\",\"menuCode\":\"0002\"},\"children\":[],\"leaf\":true},{\"id\":39,\"parentId\":0,\"name\":\"博客\",\"data\":{\"menuUrl\":\"/list.html\",\"menuCode\":\"0004\"},\"children\":[],\"leaf\":true},{\"id\":40,\"parentId\":0,\"name\":\"项目\",\"data\":{\"menuUrl\":\"/project.html\",\"menuCode\":\"0005\"},\"children\":[],\"leaf\":true},{\"id\":41,\"parentId\":0,\"name\":\"工具\",\"data\":{\"menuUrl\":\"/tools.html\",\"menuCode\":\"0006\"},\"children\":[],\"leaf\":true}]";
List<?> tree = fromJson(data, TypeToken.getParameterized(List.class, Tree.class).getType());
System.out.println(toJson(tree));
}
1.3、解析结果
[{"id":37.0,"parentId":0.0,"name":"首页","data":{"menuUrl":"/","menuCode":"0001"},"children":[],"leaf":true},{"id":38.0,"parentId":0.0,"name":"书籍","data":{"menuUrl":"/grid.html","menuCode":"0002"},"children":[],"leaf":true},{"id":39.0,"parentId":0.0,"name":"博客","data":{"menuUrl":"/list.html","menuCode":"0004"},"children":[],"leaf":true},{"id":40.0,"parentId":0.0,"name":"项目","data":{"menuUrl":"/project.html","menuCode":"0005"},"children":[],"leaf":true},{"id":41.0,"parentId":0.0,"name":"工具","data":{"menuUrl":"/tools.html","menuCode":"0006"},"children":[],"leaf":true}]
1.4、问题
int类型的id被转换成了double类型。
二、解决方案
2.1、旧的(网上千篇一律的复制方案)
新建TypeAdapter接口的子类,自行转换。网上疯传的就是创建:DataTypeAdapter,代码不再贴出。
2.2、Gson修改方案
2.2.1、分析
其实通过分析GsonBuilder的构造方法源码:
public GsonBuilder() {
...略...
this.objectToNumberStrategy = ToNumberPolicy.DOUBLE;
this.numberToNumberStrategy = ToNumberPolicy.LAZILY_PARSED_NUMBER;
}
我们可以发现,在构造的时候默认了Object和Number类转换成数字类型的处理策略,可以看到,Object转换默认为ToNumberPolicy.DOUBLE的dobule的类型,因此不单单是int会被转换成double,Long类型等等数值类型都会默认被转换成dobule类型。
2.2.2、策略类
public enum ToNumberPolicy implements ToNumberStrategy {
DOUBLE {
...略...
},
LAZILY_PARSED_NUMBER {
public Number readNumber(JsonReader in) throws IOException {
return new LazilyParsedNumber(in.nextString());
}
},
LONG_OR_DOUBLE {
...略...
},
BIG_DECIMAL {
...略...
};
private ToNumberPolicy() {
}
}
通过上面的策略类源码,我们发现:LAZILY_PARSED_NUMBER就是处理数值类型的枚举,查看LazilyParsedNumber源码,我们发现确实进行了细致的数值类型处理划分:
public final class LazilyParsedNumber extends Number {
private final String value;
public LazilyParsedNumber(String value) {
this.value = value;
}
public int intValue() {
try {
return Integer.parseInt(this.value);
} catch (NumberFormatException var4) {
try {
return (int)Long.parseLong(this.value);
} catch (NumberFormatException var3) {
return (new BigDecimal(this.value)).intValue();
}
}
}
public long longValue() {
...略...
}
public float floatValue() {
...略...
}
public double doubleValue() {
...略...
}
public String toString() {
return this.value;
}
private Object writeReplace() throws ObjectStreamException {
return new BigDecimal(this.value);
}
...略...
}
2.2.2、解决
既然知道构造的时候设置了默认,所以修复就很简单了,我们调用设置转换的策略方法即可:
/**
* 获取list
*
* @param json 数据源
* @param type TypeToken.getParameterized(List.class, xxx.class).getType();
*/
public static List<?> fromJson(String json, Type type) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setObjectToNumberStrategy(ToNumberPolicy.LAZILY_PARSED_NUMBER);
Gson gson = gsonBuilder.create();
return gson.fromJson(json, type);
}
测试结果:
[{"id":{"value":"37"},"parentId":{"value":"0"},"name":"首页","data":{"menuUrl":"/","menuCode":"0001"},"children":[],"leaf":true},{"id":{"value":"38"},"parentId":{"value":"0"},"name":"书籍","data":{"menuUrl":"/grid.html","menuCode":"0002"},"children":[],"leaf":true},{"id":{"value":"39"},"parentId":{"value":"0"},"name":"博客","data":{"menuUrl":"/list.html","menuCode":"0004"},"children":[],"leaf":true},{"id":{"value":"40"},"parentId":{"value":"0"},"name":"项目","data":{"menuUrl":"/project.html","menuCode":"0005"},"children":[],"leaf":true},{"id":{"value":"41"},"parentId":{"value":"0"},"name":"工具","data":{"menuUrl":"/tools.html","menuCode":"0006"},"children":[],"leaf":true}]
三、技术支持
1、Litepal智能开发管理系统
2、提供各种管理系统、APP开发、小程序开发、网站开发
3、提供Java程序开发,Android与IOS以及uniapp开发与技术支持
4、微信:qq690898091,QQ:690898091