Gson提供了fromJson()toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。

今天在使用 fromJson()遇到一个无法识别泛型的问题。

我的需求是通过fromJson() 反序列化返回一个List。

主要代码如下:

1
2
3
4
5
6
7
8
public List<T> select(T var) {
List<T> list = Lists.newArrayList();
...
...
JsonArray jsonArray = jsonObject.getAsJsonObject("d").getAsJsonArray("results");
list = gson.fromJson(jsonArray, new TypeToken<ArrayList<T>>() {}.getType());
return list;
}

T 的当前类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Getter
@Setter
public class AvsPerson {
/**
* person
*/
@SerializedName(value = "Person")
private String person;
/**
* 业务员编号
*/
@SerializedName(value = "PersonWorkAgreement")
private String personWorkAgreement;
/**
* 业务员姓名
*/
@SerializedName(value = "PersonFullName")
private String personFullName;
}

jsonArray的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"__metadata": {
"id": "1",
"uri": "2",
"type": "3"
},
"Person": "9980000020",
"PersonWorkAgreement": "50000000",
"PersonFullName": "Sarah Huang"
},
{
"__metadata": {
"id": "1",
"uri": "2",
"type": "3"
},
"Person": "9980000021",
"PersonWorkAgreement": "50000002",
"PersonFullName": "Shanna Sun"
}

反序列化后List中的值:

反序列化后的数据

数据是已经到list中了,但是它不是我需要的那个AvsPerson类型,而是完全把jsonArray中的数据反序列化为一个Map。

DEBUG跟一下发现如下:

debug

直接把T当成一个Type 了。。

因此我怀疑Gson没有识别到我使用的泛型类,所以直接当成 Object类型了,我测试把 T 换成Object是一样的结果,Type中则显示为Object类型了。

经过一番摸索,解决方案如下:

使用 Guava,它也是Google家的,直接引入依赖即可:

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>

使用如下方法:

1
2
3
4
5
public <T> Type setModelAndGetCorrespondingList(Class<T> type) {
return new TypeToken<ArrayList<T>>() {}
.where(new TypeParameter<T>() {}, type)
.getType();
}

这里的 TypeToken 使用的是 Guava 下的包了,注意更换。

在代码中调用这个方法即可:

1
2
3
4
5
6
7
8
public List<T> select(T var) {
List<T> list = Lists.newArrayList();
...
...
JsonArray jsonArray = jsonObject.getAsJsonObject("d").getAsJsonArray("results");
list = gson.fromJson(jsonArray, classHelper.setModelAndGetCorrespondingList(var.getClass()));
return list;
}

更改后再次 debug 后 Type 的类型正常了!

Type类型正常

得到的List内容也恢复正常:

List数据正常

具体的原因可以看这里:https://stackoverflow.com/questions/20773850/gson-typetoken-with-dynamic-arraylist-item-type