Gson轉(zhuǎn)換導(dǎo)致int轉(zhuǎn)為double問(wèn)題解決

當(dāng)我們用Object或者M(jìn)ap中的泛型使用了Object,我們將json轉(zhuǎn)換之后,發(fā)現(xiàn)數(shù)據(jù)中的所以數(shù)值都變成了double類型,0變?yōu)榱?.0,導(dǎo)致后續(xù)程序可能出現(xiàn)一些問(wèn)題。

查看Gson的源碼, 會(huì)發(fā)現(xiàn)Object最后默認(rèn)的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方法發(fā)現(xiàn)所有的Number類型都被轉(zhuǎn)成了double類型,想要修改掉這個(gè)問(wèn)題,需要自己實(shí)現(xiàn)一個(gè)TypeAdapter,處理Number類型的問(wèn)題,自己重寫(xiě)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:
                /**
                 * 改寫(xiě)數(shù)字的處理邏輯,將數(shù)字值分為整型與浮點(diǎn)型。
                 */
                double dbNum = in.nextDouble();

                // 數(shù)字超過(guò)long的最大值,返回浮點(diǎn)類型
                if (dbNum > Long.MAX_VALUE) {
                    return dbNum;
                }
                // 判斷數(shù)字是否為整數(shù)值
                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);
    }
}

經(jīng)過(guò)自己的處理將number類型都進(jìn)行了轉(zhuǎn)換,分別轉(zhuǎn)為int、long和double,這樣就可以解決int轉(zhuǎn)為double的問(wèn)題。
之后將自己重寫(xiě)的TypeAdapter注冊(cè)一下

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

這樣使用返回的Gson對(duì)象進(jìn)行轉(zhuǎn)換就不會(huì)出現(xiàn)上述的問(wèn)題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容