Gson反序列化 int类型变double类型

Gson反序列化 int类型变double类型

经网上资料查找,序列化的逻辑在 com.google.gson.internal.bind.ObjectTypeAdapter 类中。
将源码拷贝出来,修改 Number 处理逻辑。


  @Override public Object read(JsonReader in) throws IOException {
    JsonToken token = in.peek();
    switch (token) {
    case BEGIN_ARRAY:
      List<Object> list = new ArrayList<Object>();
      in.beginArray();
      while (in.hasNext()) {
        list.add(read(in));
      }
      in.endArray();
      return list;

    case BEGIN_OBJECT:
      Map<String, Object> map = new LinkedTreeMap<String, Object>();
      in.beginObject();
      while (in.hasNext()) {
        map.put(in.nextName(), read(in));
      }
      in.endObject();
      return map;

    case STRING:
      return in.nextString();
	
	// 修改这里的逻辑,避免int转成double
    case NUMBER:
      String s = in.nextString();
      if (s.contains(".")) {
        return Double.valueOf(s);
      } else {
        try {
          return Integer.valueOf(s);
        } catch (Exception e) {
          return Long.valueOf(s);
        }
      }

    case BOOLEAN:
      return in.nextBoolean();

    case NULL:
      in.nextNull();
      return null;

    default:
      throw new IllegalStateException();
    }
  }

利用反射将修改好的类重新赋值给gson

浏览Gson源码,发现在构造函数中,Gson会将 ObjectTypeAdapter 添加到 factories集合中。
大体思路如下:

  1. 反射获取到 factories 属性。
  2. 获取集合中 ObjectTypeAdapter 的索引
  3. 将自定义后的 ObjectTypeAdapter 覆盖原有 ObjectTypeAdapter

代码实现

  Gson gson = new GsonBuilder().create();
  // 获取 factories 属性
            Field declaredField = Gson.class.getDeclaredField("factories");
            declaredField.setAccessible(true);
            Object factories = declaredField.get(gson);
 // 浏览源码得知 factories 集合类型是 UnmodifiableRandomAccessList
 // 该集合中有一个list 属性存储了 typeAdapter
            Class<?>[] declaredClasses = Collections.class.getDeclaredClasses();
            // 循环从父类查找 
            Field listField = myDeclaredField(factories, "list");
            listField.setAccessible(true);
   // 获取 typeAdapter集合
            List<TypeAdapterFactory> list = (List<TypeAdapterFactory>) listField.get(factories);
     // 找到 ObjectTypeAdapter 索引位置
            int i1 = list.indexOf(ObjectTypeAdapter.FACTORY);
     // 使用自定义 ObjectTypeAdapter 将其替换
            list.set(i1, com.xxx.frame.util.gsonAdapter.ObjectTypeAdapter.FACTORY);


// 反射循环向上查找类属性
public static Field myDeclaredField(Object object, String fieldName) {
        Class<?> clazz = object.getClass();
        Field declaredField;
        while (clazz != Object.class) {
            try {
                declaredField = clazz.getDeclaredField(fieldName);
                return declaredField;
            } catch (Exception e) {
                // 找不到属性报:NoSuchFieldException
                logger.error(e.getClass().getName());
            }
            clazz = clazz.getSuperclass();
        }
        return null;
    }
测试代码
  public static void main(String[] args) throws Exception {
        String a = "{\"Integer\":123,\"Float\":123.0,\"String\":\"abc\",\"Boolean\":true,\"Double\":123.0}";
        HashMap hashMap = gson.fromJson(a, HashMap.class);
        System.out.println(hashMap.toString());
    }
输出结果
{Integer=123, Float=123.0, String=abc, Boolean=true, Double=123.0}

参考链接

  1. 反射修改不可变集合UnmodifiableList
  2. 彻底解决 Gson 将 int 转换为 double 的问题
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值