Ondrej Tokar
Ondrej Tokar

Reputation: 5070

Java generic method doesn't work as expected

I am trying to make a generic method for data deserialization.

My code:

public <T> ExportedData<T> getExportData(T classType, String exportUri) {
    Response response = _client.get(exportUri);
    // System.out.println(response.body.toString());
    ExportedData<T> exportedData = GsonSingleton.getGson().fromJson(response.body.toString(), new TypeToken<ExportedData<T>>() {
        }.getType());
    return exportedData;
}

The response.body:

{"totalResults":2,"limit":50000,"offset":0,"count":2,"hasMore":false,"items":[{"DevicesIDs":"","EmailAddress":"[email protected]"},{"DevicesIDs":"","EmailAddress":"[email protected]"}]}

The way I call the generic method:

ExportedData<AccengageOutboundContact> exportedData = generalBulkHelper.getExportData(new AccengageOutboundContact(), uriLimitAndOffset);

The AccengageOutboundContact:

public class AccengageOutboundContact {

   public String EmailAddress;
   public String DevicesIDs;

}

And the ExportedData:

public class ExportedData<T> {
    public int totalResults;
    public int limit;
    public int offset;
    public int count;
    public boolean hasMore;
    public List<T> items;
}

I would expect to get an ArrayList of AccengageOutboundContact objects. What I am getting is ArrayList of StringMap.

Any idea what am I doing wrong?

Upvotes: 2

Views: 85

Answers (1)

Jorn Vernee
Jorn Vernee

Reputation: 33845

I've seen this one a bunch of times, but there does not seem to be a good duplicate to link.


Basically the problem is that T is erased to Object, in your generic method. So the TypeToken that is created, does not hold the needed information.

This results in deserializtion to a StringMap.


You can fix this by passing a complete TypeToken to your method:

public <T> ExportedData<T> getExportData(TypeToken<ExportedData<T>> tt, String exportUri) {
    Response response = _client.get(exportUri);
    // System.out.println(response.body.toString());
    ExportedData<T> exportedData = GsonSingleton.getGson().fromJson(response.body.toString(),
        tt.getType());
    return exportedData;
}

Then call like:

generalBulkHelper.getExportData(new TypeToken<ExportedData<AccengageOutboundContact>>(){},
    uriLimitAndOffset);

Upvotes: 2

Related Questions