簡體   English   中英

在GSON中使用泛型

[英]Using generics with GSON

我正在使用GSON將JSON解碼為T類型的對象,例如

public T decode(String json) {
    Gson gson = new Gson();
    return gson.fromJson(json, new TypeToken<T>() {}.getType());
}

但是,這將返回異常-

java.lang.AssertionError:意外的類型。 期望以下類型之一:java.lang.reflect.ParameterizedType,java.lang.reflect.GenericArrayType,但得到:sun.reflect.generics.reflectiveObjects.TypeVariableImpl,類型標記為:T

我認為通過使用TypeToken可以避免Type Erasure。

我錯了嗎?

謝謝

首先,我看不到像這樣包裝Gson有什么用。

對於您的問題,有關泛型T本身的信息在運行時不可用。 它已被刪除。 它僅在編譯時可用。 您想使用實際類型來參數化它,而不是像new TypeToken<List<String>>

如您所見,由於Java中缺少經過修飾的泛型(不可能執行T t = new T() ),因此Gson本身被迫使用TypeToken方法。 否則,Gson會以一種更為優雅的方式做到這一點。

為了能夠傳遞實際的類型,您必須重新發明TypeToken已經在做的事情。 這沒有任何意義:)只是重用它,或者直接使用Gson而不將其包裝在這樣的輔助類中。

我認為第一個答案並未指出實際的解決方案:您還必須將Class實例與T一起傳遞,如下所示:

public T decode(String json, Class<T> cls) {
    Gson gson = new Gson();
    return gson.fromJson(json, cls);
}

這是因為這里的“ T”是變量類型,而不是類型引用; 並且僅由編譯器用於添加隱式強制轉換和驗證類型兼容性。 但是,如果您通過實際課程,則可以使用; 編譯器將檢查類型兼容性以減少不匹配的機會。

或者,您可以輸入TypeToken並傳遞它; 但是TypeToken必須使用實型而不是類型變量構造; 類型變量在這里幾乎沒有用。 但是,如果您確實想包裝東西,則不希望調用者使用TypeToken(這是Gson類型)。

同樣的包裝機制也可以與您提到的Jackson之類的其他庫一起使用。

我對此的解決方案是使用json解析器並將其分解成碎片

public static <TT> PushObj<TT> fromJSON(String json, Class<TT> classType)
{
    JsonObject jObj = new JsonParser().parse(json).getAsJsonObject();
    String type = jObj.get("type").getAsString();
    JsonObject job = jObj.get("object").getAsJsonObject();
    TT obj = new Gson().fromJson(job, classType);
    return new PushObj<TT>(type, obj);
}

對象結構為:{String:Type,Generic:Object}

變量是:jObj是傳入的字符串的JSONObject,而job是通用對象的JSONObject。

因此,我使用json解析器分別獲取類型和對象的反射。

暫無
暫無

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

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