2012-04-08 42 views
9

的我有這樣的代碼片段:GSON轉換,而不是到的LinkedHashMap我的對象

public abstract class Repository<Entity extends BaseObject> { 

... 

public void readFromJson(){ 
    String content = "JSON content here"; 
    Gson gson = new Gson(); 
    Type entityType = new TypeToken<JSONObject<Entity>>(){}.getType(); 

    jsonObject = gson.fromJson(content, entityType); 

    for (Entity ent : jsonObject.getEntities()) ; 
    } 
} 

當我嘗試做的foreach我的實體對象不再是實體類型,但LinkedHashMap的,我得到這個異常:JAVA .lang.ClassCastException:java.util.LinkedHashMap中不能轉換到com.tranca.bookstore.domain.shared.BaseObject

這裏是的JSONObject類(由我創建)

public class JSONObject<Entity> { 

private List<Entity> entities = new ArrayList<Entity>(); 
private long lastId = -1; 
public List<Entity> getEntities() { 
    return entities; 
} 
public void setEntities(List<Entity> entities) { 
    this.entities = entities; 
} 
public long getLastId() { 
    return lastId; 
} 
public void setLastId(long lastId) { 
    this.lastId = lastId; 
} 

public void incrementLastId() { 
    this.lastId++; 
} 

}

也許基本對象是相關的,所以我會在這裏把代碼:

public abstract class BaseObject implements Serializable { 

protected long id = (long) -1; 
protected int version = 0; 

protected BaseObject(){} 

public long getId() { 
    return id; 
} 
public void setId(long id) { 
    this.id = id; 
} 
public int getVersion() { 
    return version; 
} 
public void setVersion(int version) { 
    this.version = version; 
} 

} 
+0

您使用的是Gson 2.1嗎? – 2012-04-09 13:56:55

回答

1

終於拿到了!

的問題是:

新TypeToken <的JSONObject <實體>>(){}的getType();

返回的JSONObject <的類型T>不是被延伸庫子類的特定實體(例如UserRepository延伸庫<用戶>)。

訣竅是創建一個抽象方法來強制子類設置反序列化的類型。

總之,如果你得到這個錯誤,確保你有正確類型的類(如果你使用子類,確保它返回的是你的子類的類型而不是超類)。

+6

對不起,我遇到了同樣的問題,但我不明白你的答案,請你澄清一下?謝謝! – 2012-04-21 06:17:24

+1

@JonathanLeung:如果我理解正確,問題是表達式'new TypeToken >(){}'的每次執行都會實例化一個匿名類的實例。 'Entity'實際上不是一個類,它只是'Repository'的一個類型參數,所以它在這個時候被完全擦除,甚至不能真正反映。 ('TypeToken'東西使用反射來檢查類層次結構以繞過擦除,但當類本身引用類型參數時它不起作用。) – ruakh 2013-11-27 08:18:17

+1

對不起。你的答案再次不清楚。如果你能提供有意義的解決方案,那將是一件好事。 – 2014-11-25 11:53:30

3

我有相同/類似的問題。爲了給出一個更明確的答案稍有不同的上下文:

我曾跟隨其產生的誤差「com.google.gson.internal.LinkedTreeMap不能轉換爲MyType的」製法:我想

/** 
    * Reads a LinkedHashMap from the specified parcel. 
    * 
    * @param <TKey> 
    *   The type of the key. 
    * @param <TValue> 
    *   The type of the value. 
    * @param in 
    *   The in parcel. 
    * @return Returns an instance of linked hash map or null. 
    */ 
    public static <TKey, TValue> LinkedHashMap<TKey, TValue> readLinkedHashMap(Parcel in) { 
    Gson gson = JsonHelper.getGsonInstance(); 
    String content = in.readString(); 
    LinkedHashMap<TKey, TValue> result = gson.fromJson(content, new TypeToken<LinkedHashMap<TKey, TValue>>(){}.getType()); 
    return result; 
    } 

一種簡單的通用方式來讀/寫鏈接的hashmap。上述解決方案不起作用,因爲根據我的理解,編譯後會丟失帶有TKey和TValue的TypeToken的類型信息。這就是問題所在。如果您將代碼更改爲以下示例,那麼它就可以工作,因爲現在我們明確定義了類型標記。我沒有那麼多的java,我明白爲什麼在這種情況下可以在運行時讀取類型信息。

/** 
    * Reads a LinkedHashMap from the specified parcel. 
    * 
    * @param <TKey> 
    *   The type of the key. 
    * @param <TValue> 
    *   The type of the value. 
    * @param in 
    *   The in parcel. 
    * @return Returns an instance of linked hash map or null. 
    */ 
    public static <TKey, TValue> LinkedHashMap<TKey, TValue> readLinkedHashMap(Parcel in, TypeToken<LinkedHashMap<TKey, TValue>> typeToken) { 
    Gson gson = JsonHelper.getGsonInstance(); 
    Type type = typeToken.getType(); 
    String content = in.readString(); 
    LinkedHashMap<TKey, TValue> result = gson.fromJson(content, type); 
    return result; 
    } 

而現在只需要調用上面的函數:

readLinkedHashMap(in, new TypeToken<LinkedHashMap<UUID, MyObject>>(){}); 

旁註1:當writign鏈接的哈希地圖,你不需要指定任何類型的令牌。 toJson(地圖)就足夠了。

旁註2(對我有問題):默認情況下,gson使用toString()來序列化密鑰。如果您爲可能是更復雜類型的密鑰類型註冊類型適配器,則在序列化時不應用此類型適配器,但在反序列化時應用此類適配器。這導致了一個不一致的,因此失敗的過程。以下選項激活complex map key serialization

gsonBuilder.enableComplexMapKeySerialization() 
+1

主要是'gsonBuilder.enableComplexMapKeySerialization()'解決了我的問題 – CrandellWS 2016-05-20 10:59:01

相關問題