简体   繁体   中英

Use Gson library with a generic class as a field of the class to serialize

After multiple researches on Google and Stack Overflow, i haven't found a similar case to mine.

I need to use Gson library to convert a Java object to Json. The fact is that this object contains a field with a custom generic type, as follow :

SendData.java :

public class SendData {
  private SendDataRequestObject<?> sendData;

  // Constructor + Getters and Setters
}

Here is the class definition of SendDataRequestObject :

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

  //Constructor + Getters and Setters
}

And finally, the class definition of MyRequest which may be injected in SendDataRequestObject as the T parameter

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

  //Constructor + Getters and Setters
}

Actually, I'm able to parse SendDataRequestObject with Gson library as follow :

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));

The output is properly set and every fields, even the generic one, are included into the final json string :

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

But what I need is to parse SendData class, not SendDataRequestObject class. When I try to convert this class into json string, I obtain this output :

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

So, we can see that parameters field of SendDataRequestObject is not converted to Json, probably because this is a generic class.

If anybody has an idea of how to do it, I would be very grateful !

You can't do this without somehow knowing the type T at compile time in some manner due to Java's type erasure.

One option for this is the JSON can contain some information specifying the type, eg

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

If you then make SendData generic eg

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

you can then parse the JSON once to find out the sendDataType :

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

and use that to create a TypeToken of the right type:

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

And then parse the JSON again specifying the generic type now that you know it:

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

This works because our switch statement knows the possible types at compile time and can create TypeTokens for them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM