亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何正確使用 Gson 通過靜態實用程序方法反序列化泛型類型的對象?

如何正確使用 Gson 通過靜態實用程序方法反序列化泛型類型的對象?

慕哥6287543 2022-07-14 10:35:47
我見過許多其他類似的問題,但我認為在這些問題之上還有一定程度的抽象會有所不同。即,我有一個帶有靜態泛型包裝方法的實用程序類來反序列化泛型類型的對象(在構建時未知):public final class Utils {    public static final Gson sGson = new Gson();    public static synchronized <T> T fromJson(String doc) {        return sGson.fromJson(doc, new TypeToken<T>(){}.getType());    }}一個簡單的類來測試它:public class TestDocument {    public TestDocument(String test) {        this.test = test;    }    public String test;}這很好用:assertEquals(   new TestDocument("test").test,    ((TestDocument) Utils.sGson.fromJson(                      "{\"test\": \"test\"}",                       new TypeToken<TestDocument>(){}.getType())).test);但是,雖然靜態通用實用程序方法沒有,但看起來像調用它的等效方法:assertEquals(   new TestDocument("test").test,    Utils.<TestDocument>fromJson("{\"test\": \"test\"}").test);引發以下異常:java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap 無法轉換為 TestDocument有沒有辦法通過通用方法使其工作?
查看完整描述

3 回答

?
江戶川亂折騰

TA貢獻1851條經驗 獲得超5個贊

有一些類型使用提示:

  • <T>由于泛型類型被擦除,在不傳遞實際類型的情況下使用是一個騙局。

  • 傳遞類型 asClass<T>不是一個好主意,因為###.class它僅代表 JVM 加載的類(原始類型除外)。有了它,Class<List<String>>并且Class<List<Map<Integer, ?>>>完全一樣的List.class丟失類型參數化,因此使 Gson(反)序列化工作時沒有考慮到正確的類型(例如,如果我記得的話,LinkedHashTreeMap 就是一個很好的例子)。

  • Gson 主要使用Type它是可以由 Java 類型系統表示的任何類型(包括類ParameterizedType、等)的超類型接口。見https://google.github.io/gson/apidocs/com/google/gson/Gson.html#fromJson-java.lang.String-java.lang.reflect.Type-

  • TypeToken是 Java 中泛型類型持有者的一個很好的例子,包括它根據構建方式生成正確的類型信息。它可用于使您的方法類型安全:public static <T> T fromJson(String doc, TypeToken<? extends T> typeToken) { return sGson.fromJson(doc, typeToken.getType()); }. 類型標記可以緩存到公共的(是的)靜態最終字段中,因為它是不可變的并且跨線程是線程安全的。

獎金:

  • 不需要synchronizedGson實例也是線程安全的。


查看完整回答
反對 回復 2022-07-14
?
一只萌萌小番薯

TA貢獻1795條經驗 獲得超7個贊

如果可能的話,Gson可能已經添加了這個方法,它可能看起來像這樣:

TestDocument document = gson.<TestDocument>fromJson(json);

具有此簽名的方法:

public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException

包括JavaDoc

該方法將指定的 Json 反序列化為指定類的對象。如果指定的類是泛型類型,則不適合使用,因為Java 的類型擦除特性,它不會具有泛型類型信息。因此,如果所需的類型是泛型類型,則不應使用此方法。請注意,如果指定對象的任何字段都是泛型,則此方法可以正常工作,只是對象本身不應該是泛型類型。對于對象是泛型類型的情況,調用 fromJson(String, Type)。如果您在 aReader而不是 a中有 Json String,請fromJson(Reader, Class)改用。

甚至第二個參數名稱也是classOfT有意義the class of T的。


查看完整回答
反對 回復 2022-07-14
?
婷婷同學_

TA貢獻1844條經驗 獲得超8個贊

看起來如果不顯式傳遞實際類型以便在構建時知道它,就不可能在 Java 中執行此操作。

這是一個解決方案:

    public static synchronized <T> T fromJson(String doc, Class<T> type) {
            return sGson.fromJson(doc, type);
    }

然后測試通過:

    assertEquals((new TestDocument("test").test), Utils.<TestDocument>fromJson("{\"test\": \"test\"}", TestDocument.class).test);

在這個特定的(故意過度簡化的)示例中,這看起來可以以更簡單、更優雅的方式完成,但當它是更大、更復雜場景的一部分時,它可能是唯一的選擇。


查看完整回答
反對 回復 2022-07-14
  • 3 回答
  • 0 關注
  • 155 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號