说明
此问题出于研发阶段发现的问题,经过翻阅源码分析得出如下解决方案, 个人感觉来讲 对比fastjson ,gson没有那么懂得我们的心,很多时候 我们理所当然的认为序列化的时候就应该是这样的,但是gson并没有给与那么完美的支持,更多的时候还需要我们针对性的定制插件来扩展支持。
另外也简单说下不用fastjson的原因,fastjson在实际使用中确实是很好用,大部分情况效果都比较符合开发者的预期,但是有一点比较致命的就是安全问题,一直以来,生产环境因为fastjson升级导致的兼容问题层出不穷,这就是不选用fastjson的最主要原因
问题样例说明
public static void main(String[] args) {
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
builder.registerTypeAdapter(new TypeToken<Map<String,Object>>(){}.getType(),new MapTypeAdapter());
Gson gson = builder.create();
String value = "{\"amount\":20000}";
Map<String, Object> map = gson.fromJson(value, new TypeToken<Map<String, Object>>() {
}.getType());
System.out.println(map.get("amount"));
GsonBuilder builder2 = new GsonBuilder();
builder2.setDateFormat("yyyy-MM-dd HH:mm:ss");
Gson gson2 = builder2.create();
Map<String, Object> map2 = gson2.fromJson(value, new TypeToken<Map<String, Object>>() {
}.getType());
System.out.println(map2.get("amount"));
}
如上代码 一个JSON转换成Map<String, Object> 然后值类型会出现问题 从整形数据变成浮点数 ,字符串则没有任何问题
执行结果如下
20000
20000.0
问题方案
如上代码 问题已经解决 解决方案和原因介绍
com.google.gson.internal.bind.ObjectTypeAdapter 参考gson的源码的这个类
反序列化的时候 NUMBER类型 的时候 默认是按double处理的所以加上了浮点数的。0 然后模拟此类定制一个TypeAdapter 解决此问题就可以了
public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
switch(token) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList();
in.beginArray();
while(in.hasNext()) {
list.add(this.read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedTreeMap();
in.beginObject();
while(in.hasNext()) {
map.put(in.nextName(), this.read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
// NUMBER 值类型重写下方法 把不需要是浮点数的修改一下解析返回值即可
case NUMBER:
return in.nextDouble();
case BOOLEAN:
return in.nextBoolean();