美文网首页Android开发Android进阶之路Android学习
Gson转换导致int转为double问题解决

Gson转换导致int转为double问题解决

作者: lebronzhen | 来源:发表于2019-12-28 18:06 被阅读0次

    当我们用Object或者Map中的泛型使用了Object,我们将json转换之后,发现数据中的所以数值都变成了double类型,0变为了0.0,导致后续程序可能出现一些问题。

    查看Gson的源码, 会发现Object最后默认的TypeAdapter使用的是com.google.gson.internal.bind包下的ObjectTypeAdapter,里边的处理如下:

    /**
     * Adapts types whose static type is only 'Object'. Uses getClass() on
     * serialization and a primitive/Map/List on deserialization.
     */
    public final class ObjectTypeAdapter extends TypeAdapter<Object> {
      public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
        @SuppressWarnings("unchecked")
        @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
          if (type.getRawType() == Object.class) {
            return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
          }
          return null;
        }
      };
    
      private final Gson gson;
    
      ObjectTypeAdapter(Gson gson) {
        this.gson = gson;
      }
    
      @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();
    
        case NUMBER:
          return in.nextDouble();
    
        case BOOLEAN:
          return in.nextBoolean();
    
        case NULL:
          in.nextNull();
          return null;
    
        default:
          throw new IllegalStateException();
        }
      }
    
      @SuppressWarnings("unchecked")
      @Override public void write(JsonWriter out, Object value) throws IOException {
        if (value == null) {
          out.nullValue();
          return;
        }
    
        TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
        if (typeAdapter instanceof ObjectTypeAdapter) {
          out.beginObject();
          out.endObject();
          return;
        }
    
        typeAdapter.write(out, value);
      }
    }
    
    

    查看read方法发现所有的Number类型都被转成了double类型,想要修改掉这个问题,需要自己实现一个TypeAdapter,处理Number类型的问题,自己重写TypeAdapter,代码如下:

    
    public class DataTypeAdapter extends TypeAdapter<Object> {
        private final TypeAdapter<Object> delegate = new Gson().getAdapter(Object.class);
    
        @Override
        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(read(in));
                    }
                    in.endArray();
                    return list;
    
                case BEGIN_OBJECT:
                    Map<String, Object> map = new LinkedTreeMap<>();
                    in.beginObject();
                    while (in.hasNext()) {
                        map.put(in.nextName(), read(in));
                    }
                    in.endObject();
                    return map;
    
                case STRING:
                    return in.nextString();
    
                case NUMBER:
                    /**
                     * 改写数字的处理逻辑,将数字值分为整型与浮点型。
                     */
                    double dbNum = in.nextDouble();
    
                    // 数字超过long的最大值,返回浮点类型
                    if (dbNum > Long.MAX_VALUE) {
                        return dbNum;
                    }
                    // 判断数字是否为整数值
                    long lngNum = (long) dbNum;
                    if (dbNum == lngNum) {
                        try {
                            return (int) lngNum;
                        } catch (Exception e) {
                            return lngNum;
                        }
                    } else {
                        return dbNum;
                    }
    
                case BOOLEAN:
                    return in.nextBoolean();
    
                case NULL:
                    in.nextNull();
                    return null;
    
                default:
                    throw new IllegalStateException();
            }
        }
    
        @Override
        public void write(JsonWriter out, Object value) throws IOException {
            delegate.write(out, value);
        }
    }
    

    经过自己的处理将number类型都进行了转换,分别转为int、long和double,这样就可以解决int转为double的问题。
    之后将自己重写的TypeAdapter注册一下

    new GsonBuilder().registerTypeAdapter(new TypeToken<Map<String,Object>>(){}.getType(),new DataTypeAdapter()).create();
    

    这样使用返回的Gson对象进行转换就不会出现上述的问题。

    相关文章

      网友评论

        本文标题:Gson转换导致int转为double问题解决

        本文链接:https://www.haomeiwen.com/subject/nswsoctx.html