23

I have a method for reading JSON from a service, I'm using Gson to do my serialization and have written the following method using type parameters.

public T getDeserializedJSON(Class<T> aClass,String url)
{
    Reader r = getJSONDataAsReader(url);
    Gson gson = new Gson();
    return gson.fromJson(r, aClass);
}

I'm consuming json which returns just an array of a type e.g.

[
 { "prop":"value" }
 { "prop":"value" }
]

I have a java class which maps to this object let's call it MyClass. However to use my method I need to do this:

RestClient<ArrayList<MyClass>> restClient = new RestClient<ArrayList<MyClass>>();
ArrayList<MyClass> results = restClient.getDeserializedJSON(ArrayList<MyClass>.class, url);

However, I can't figure out the syntax to do it. Passing just ArrayList.class doesn't work.

So is there a way I can get rid of the Class parameter or how do I get the class of the ArrayList of MyClass?

Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
Rob Stevenson-Leggett
  • 35,279
  • 21
  • 87
  • 141
  • https://stackoverflow.com/questions/27000227/cannot-select-parameterized-type is a related question and ultimately helped me – Uncle Iroh Oct 03 '19 at 20:24

6 Answers6

36

You can use Bozho's solution, or avoid the creation of a temporary array list by using:

Class<List<MyClass>> clazz = (Class) List.class;

The only problem with this solution is that you have to suppress the unchecked warning with @SuppressWarnings("unchecked").

Lii
  • 11,553
  • 8
  • 64
  • 88
Eyal Schneider
  • 22,166
  • 5
  • 47
  • 78
  • "The only problem with this solution is that you have to suppress the unchecked warning" - I'm not sure about that. You can as well have this warning, right? – Line Oct 11 '17 at 12:27
10

You can't. You'd have to use unsafe cast:

Class<List<MyClass>> clazz = 
   (Class<List<MyClass>>) new ArrayList<MyClass>().getClass();
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
7

As a follow up to this, I found this in the Gson docs.

Type listType = new TypeToken<List<String>>() {}.getType();

Which solves the problem of getting the type safely but the TypeToken class is specific to Gson.

Rob Stevenson-Leggett
  • 35,279
  • 21
  • 87
  • 141
  • 1
    Ok, but this actually didn't solve the generic problem! I look for something like `Type listType = new TypeToken>() {}.getType();` and the generic type `T` is passed as a method paramter like you did in your question – Khalid ElSayed Jan 30 '18 at 14:06
3

If you are using SpringFramework you could use ParameterizedTypeReference as follows:

 restClient.getDeserializedJSON(ParameterizedTypeReference<List<MyClass>>(){},url);
nonamer92
  • 1,887
  • 1
  • 13
  • 24
1

I had a similar scenario but I have a workaround to use an array instead of ArrayList

MyClass[] results = restClient.getDeserializedJSON(MyClass[].class, url);

And here what deserialize method does

You can then proceed with list as follows:

List<MyClass> r_results= Arrays.stream(results).collect(Collectors.toList());
Amado Saladino
  • 2,114
  • 23
  • 25
0

Depending on how is your requirement, but if you are ok working with array there you can provide as Class: MyClass[].class

Radu Linu
  • 1,143
  • 13
  • 29