gson轉化爲帶泛型的Map(K, V):com.google.gson.internal.LinkedTreeMap cannot be cast to xx(entity)

 

目錄

錯誤日誌:

解釋:

原因:

錯誤代碼:

解決方法

(零)、TypeToken解決

其他幾種解決思路

(一)、當Map的Key爲String類型時

正確代碼1:

(二)、通過 由Map的key組成的List,和有value組成的List解決

正確代碼2:


錯誤日誌:

    com.google.gson.internal.LinkedTreeMap cannot be cast to xx(entity)

解釋:

    LinkedTreeMap 得到的對象無法被映射到實體類

原因:

    帶泛型的map被轉成gson後,對象被擦除,變爲無屬性的Object。所以無法被還原。

錯誤代碼:

public <K, V> Map<K, V> toMap2(String json, Class<K> kClazz, Class<V> vClazz) {
    return sGson.fromJson(json, new TypeToken<Map<K, V>>() {}.getType());
}

解決方法

(零)、TypeToken解決

    /**
     * @param json map的序列化結果
     * @param <K>   k類型
     * @param <V>   v類型
     * @return Map<K       ,       V>
     */
    public <K, V> Map<K, V> toMap(String json, Class<K> kClazz, Class<V> vClazz) {
        return sGson.fromJson(json,TypeToken.getParameterized(Map.class,kClazz,vClazz).getType());
    }

其他幾種解決思路

(一)、當Map的Key爲String類型時

    爲什麼要特別說明爲key爲String呢,因爲不管你的Key爲什麼類型,通過Gson還原時得到的LinkedTreeMap 的 key都爲String類型。

    此時通過JsonObject即可解決

正確代碼1:

    public <V> Map<String, V> toStringKeyMap(String json, Class<V> vClazz) {
        Map<String, V> map = new HashMap<>();
        try {
            JsonObject obj = new JsonParser().parse(json).getAsJsonObject();
            Set<Map.Entry<String, JsonElement>> entrySet = obj.entrySet();
            for (Map.Entry<String, JsonElement> entry : entrySet) {
                String entryKey = entry.getKey();
                JsonObject object = (JsonObject) entry.getValue();
                V value = sGson.fromJson(object, vClazz);
                map.put(entryKey, value);
            }
        } catch (Exception e) {
            return null;
        }
        return map;
    }

你可能會問,那怎麼不用JsonObject轉化 JsonObject kobject = (JsonObject) entry.getKey() , 那樣不就解決問題了

因爲Key被映射爲String類型了,目前還沒找到解決辦法,也不打算在這中地方深追下去了,太費時間了。

(二)、通過 由Map的key組成的List,和有value組成的List解決

思路:先得到由Map的Key組成的keyList,再得到由value組成的valueList;之後分別序列化keyList、valueList。反序列化時,也是分別對keyList和valueList反序列化,在依次添加到map中去

正確代碼2:

(1)得到keyList和vList

/**
     * @param map map對象
     * @param <K> k類型
     * @param <V> v類型
     * @return keyList
     */
    public static <K, V> List<K> getMapKeyList(Map<K, V> map, Class<K> kClazz, Class<V> vClazz) {
        List<K> keyList = new ArrayList<>();
        for (Map.Entry<K, V> entry : map.entrySet()) {
            keyList.add(entry.getKey());
        }
        return keyList;
    }

    /**
     * @param map     map對象
     * @param keyList 由map的key組成的keyList
     * @param <K>     k類型
     * @param <V>     v類型
     * @return valueList
     */
    public static <K, V> List<V> getMapValueListByKey(Map<K, V> map, List<K> keyList, Class<K> kClazz, Class<V> vClazz) {
        List<V> valueList = new ArrayList<>();

        for (K k : keyList) {
            V v = map.get(k);
            valueList.add(v);
        }

        return valueList;
    }

(2)序列化keyList和valueList

    private Gson sGson = new Gson();

    public String toJson(Object object) {
        return sGson.toJson(object);
    }

(3)反序列化keyList和valueList,得到map

    /**
     * @param kJson keyList的序列化結果
     * @param vJson valueList的序列化結果
     * @param <K>   k類型
     * @param <V>   v類型
     * @return Map<K   ,   V>
     */
    public <K, V> Map<K, V> toMap(String kJson, String vJson, Class<K> kClazz, Class<V> vClazz) {
        Map<K, V> map = new HashMap<>();
        try {
            List<K> kList = toList(kJson, kClazz);
            List<V> vList = toList(vJson, vClazz);
            for (int i = 0; i < kList.size(); i++) {
                K k = kList.get(i);
                V v = vList.get(i);
                map.put(k, v);
            }
        } catch (Exception e) {
            return null;
        }
        return map;
    }

    /**
     * @param json list的序列化字符串
     * @param <T>  T類型
     * @return List<T>
     */
    public <T> List<T> toList(String json, Class<T> clazz) {
        List<T> list = new ArrayList<>();
        try {
            JsonArray array = new JsonParser().parse(json).getAsJsonArray();
            for (final JsonElement elem : array) {
                list.add(new Gson().fromJson(elem, clazz));
            }
        } catch (Exception e) {
            return null;
        }
        return list;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章