簡體   English   中英

使用 GSON 反序列化泛型類型時遇到問題

[英]Trouble deserializing generic types using GSON

我有一組 4 個類,它們代表我的數據庫對象(數據庫目前只是一個 ArrayList)。
我正在使用 GSON 將這些對象存儲在 a.txt 文件中。
一個名為Storage的 class 負責將這些對象讀取和寫入到 those.txt 文件中。
這是我的問題:我有一個通用的 object T extends MyInterface object 代表 4 個數據庫類。 我把T放在Storage方法中,所以我可以將這個 class 用於任何數據庫 object。 這是代碼:

public class Storage<T extends MyInterface> {

     Gson GSON = new Gson();

     public ArrayList<T> readAll() {
         String objectsJSON = TextFileHandler.readFromFile(fileStorageLocation); // This works
         System.out.println(objectsJSON);   // This also works  (prints out correctly)
         Type collectionType = new TypeToken<ArrayList<T>>() {}.getType();  
         return GSON.fromJson(objectsJSON, collectionType);     // This fails
     }

}

我得到以下異常:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to 
interfaces.MyInterface

你們知道它可能是什么嗎?

匿名TypeToken子類型的全部意義在於它們是在編譯時定義的,以便保存通用類型信息。 您需要做一些事情來使令牌信息動態可用。 這種方法可能有效:

private final TypeToken<ArrayList<T>> targetType;

public Storage(Class<T> dataType) {
    targetType = new TypeToken<ArrayList<T>>(){}
        .where(new TypeParameter<T>(){}, dataType);
}

public List<T> readAll() { // avoid using concrete ArrayList in public API;
                           // not a bad idea to change it in the other locations
    ...
    return GSON.fromJson(objectsJson, targetType);
}

您應該使用接口List ,而不是像ArrayList這樣的實現

public List<T> readAll() {
     String objectsJSON = TextFileHandler.readFromFile(fileStorageLocation);
     System.out.println(objectsJSON);
     Type collectionType = new TypeToken<List<T>>() {}.getType();  
     return GSON.fromJson(objectsJSON, collectionType);
 }

如果這不起作用,請檢查objectJSON是否與 JSON 格式正確。

對於任何可能正在尋找答案的人,這就是我為解決它所做的確切工作:

問題是 GSON 不知道要實例化哪個 class 因為我的Storage<T>用於幾個不同的實體。 我不得不以某種方式告訴它,每個Storage<T>實例都使用了哪個特定實體 class。 我得到的錯誤是這樣的:

Cannot cast LinkedTreeMap to MyInterface.
因為在運行時, Storage不知道要實例化哪個 class。

I'm doing a regular Java project, so I downloaded the Guava.jar and added it to my project: http://search.maven.org/remotecontent?filepath=com/google/guava/guava/23.0/guava-23.0 .jar

我修改了我的通用 class Storage<T>構造函數,以接受Class<T> dataType參數,以便它可以在運行時知道它正在用於哪個 class。 我還添加了一個私有字段TypeToken<List<T>>以便它可以存儲有關正在反序列化的 class 的信息。

本質上,我所做的只是:

import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
import com.google.gson.*;

public class Storage<T extends MyInterface> {

     // This was used so the Storage objects knows which dataType it's associated to 
     // Because T is deleted at runtime, so you can't use that.
     private TypeToken<List<T>> targetDataType;

     // I changed the constructor to take in 1 bonus argument
     public Storage(Class<T> dataType) {
          targetDataType = new TypeToken<List<T>>() {}
                        .where(new TypeParameter<T>() {}, dataType);            
     }

     public List<T> deserialize() {
         // Read JSON data into a <jsonString> variable
    
         Gson GSON = new Gson();
         return GSON.fromJson(jsonString, targetDataType.getType());
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM