使用带有泛型类的Gson库作为类的字段来序列化

时间:2016-10-25 08:31:31

标签: java json generics gson

经过对Google和Stack Overflow的多次研究,我没有找到与我相似的案例。

我需要使用Gson库将Java对象转换为Json。事实是,此对象包含具有自定义泛型类型的字段,如下所示:

SendData.java:

public class SendData {
  private SendDataRequestObject<?> sendData;

  // Constructor + Getters and Setters
}

这是SendDataRequestObject的类定义:

public class SendDataRequestObject<T> {
  private String actionType;
  private T parameters;
  private CustomClass customClass;

  //Constructor + Getters and Setters
}

最后,MyRequest的类定义可以在SendDataRequestObject中作为T参数注入

public class MyRequest {
  private Map<Integer, String> myMap;
  private String myString1;
  private String myString2;

  //Constructor + Getters and Setters
}

实际上,我可以用Gson库解析SendDataRequestObject,如下所示:

SendDataRequestObject<MyRequest> requestObject = new SendDataRequestObject<MyRequest>();
//...
//Initializing and adding fields to requestObject
//...
Type token = new TypeToken<SendDataRequestObject<MyRequest>>(){}.getType();
System.out.println(new GsonBuilder().create().toJson(requestObject, token));

输出已正确设置,每个字段(甚至是通用字段)都包含在最终的json字符串中:

{"actionType":"verify","parameters":{"myMap":{"15789":"hreher-489hre-gdsf","13057":"rtyuiop-4g8ezg","16741":"gfd456-uiop789"},"myString1":"myStringValue1","myString2":"myStringValue2"},"customClas":{"attr1":"value1","attr2":"value2"}}

但我需要的是解析SendData类,而不是SendDataRequestObject类。当我尝试将此类转换为json字符串时,我获得此输出:

{"sendData":{"actionType":"verify","parameters":{},"customClass":{"attr1":"value1","attr2":"value2"}}}

因此,我们可以看到SendDataRequestObject的参数字段未转换为Json,可能是因为这是一个泛型类。

如果有人知道该怎么做,我将非常感激!

1 个答案:

答案 0 :(得分:0)

如果没有以某种方式在编译时知道类型T,由于Java的类型擦除,你不能这样做。

一个选项是JSON可以包含指定类型的一些信息,例如:

{
  "sendDataType": "MyRequest",
  "sendData": {
     ...
   }
}

如果你然后使SendData变得通用,例如

SendData<T> { 
  private SendDataRequestObject<T> sendData; 
}

然后您可以解析JSON一次以找出sendDataType

SendData<?> genericSendData = new GsonBuilder().create().toJson(requestObject, new TypeToken<SendData<?>>(){});
String sendDataType = genericSendData.sendDataType;

并使用它来创建正确类型的TypeToken

switch(sendDataType) {
  case "MyRequest":
    return new TypeToken<MyRequest>(){};
}

然后再次解析JSON,指定你知道的泛型类型:

SendData<?> myRequestSendData = new GsonBuilder().create().toJson(requestObject, typeToken);

这是有效的,因为我们的switch语句在编译时知道可能的类型,并且可以为它们创建TypeTokens。