鍍金池/ 問答/Java  網(wǎng)絡(luò)安全/ Gson(泛型)如何“動態(tài)”反序列化類屬性ClassCastException

Gson(泛型)如何“動態(tài)”反序列化類屬性ClassCastException

這個問題實在是不知道怎么取標題

異常如下:

Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to XXX

我舉例說明:

已知有一個User類,包含了一些簡單的屬性

public class User{
    private String userName;
    private String gender;
    
    //get set方法省略
}

然后我有一個專門用于數(shù)據(jù)傳輸?shù)膉son包裝類

public class JsonMessage<T>{
    private Integer code;
    private String msg;
    private T data;
    
    //get set方法省略
}

然后我有一個主方法

public static void main(String[] args){
    //有一個待序列化的json字符串
    String jsonStr = "{'code':123,'msg':'test','data':{'userName':'baofeidyz','gender':'male'}}";
    //然后使用Gson序列化
    Gson gson = new Gson();
    JsonMessage<User> message = gson.fromJson(jsonStr,JsonMessage.class);
    //然后在這里我嘗試獲取data中的數(shù)據(jù),就報
    //Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to User
}

可是當(dāng)我不使用泛型的時候就是OK的:

我這里有一個新的json包裝類

public class JsonMessage2{
    private Integer code;
    private String msg;
    private User data;
    
    //get set方法省略
}

然后我又新建了一個新的main方法:

public static void main(String[] args){
    //還是那個待序列化的json字符串
    String jsonStr = "{'code':123,'msg':'test','data':{'userName':'baofeidyz','gender':'male'}}";
    //然后使用Gson序列化
    Gson gson = new Gson();
    //這里換成了新的包裝類
    JsonMessage2 message = gson.fromJson(jsonStr,JsonMessage2.class);
    //然后就成功獲取到了數(shù)據(jù)
}

代碼是我在segmentfault網(wǎng)頁現(xiàn)敲的,但是問題是和我實際問題一樣。
個人覺得主要是我對泛型和Gson的序列化方式理解有問題,所以想請教一下各位,感謝!

回答
編輯回答
無標題

不同框架/庫有個字的拿泛型參數(shù)的類,不過原理都一樣

  • Gson 是 TypeToken
  • Jackson 是 TypeReference
  • Spring 也有自己的 ParameterizedTypeReference

不過題主要在 @RequestBody 里用就非常奇怪了…

2017年6月6日 00:45
編輯回答
別硬撐

我試了一下,GSON 2.7 并沒有出現(xiàn)這個異常。

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.7</version>
</dependency>
2018年8月14日 08:39
編輯回答
悶油瓶

自問自答了。

我解決了。

在Gson反序列化的過程中,如果你需要傳泛型需要這樣操作:

JsonMessage<User> message = gson.fromJson(jsonStr,new TypeToken<JsonMessage<User>>(){}.getType());

其實我以前就遇到過這個問題,只是這次發(fā)生的場景變了,這個問題實際上是在寫SpringBoot的Controller的時候遇到的

最后的解決方案是修改傳入?yún)?shù)的key,需要和包裝類的屬性名相同才可以,不過建議徹底去除jackson改成集成gson會比較好

然后就可以非常簡單的使用@RequestBody來拿到數(shù)據(jù)對象

2017年5月9日 03:43