Reputation: 387
I want to use generic type in gson TypeToken, like this:
public static <T> T execute(String s) throws SecurityException {
return new Gson().fromJson(s, new TypeToken<T>(){}.getType());
}
public static void main(String[] args) {
String s = "[{\"username\": \"abc\", \"password\": \"abc\"}, {\"username\": \"abc1\", \"password\": \"abc1\"}]";
List<Auth> a1 = new Gson().fromJson(s, new TypeToken<List<Auth>>(){}.getType());
System.out.println(a1);
System.out.println("a1 class: " + a1.get(0).getClass());
List<Auth> a2 = TypeClass.execute(s);
System.out.println(a2);
System.out.println("a2 class: " + a2.get(0).getClass());
}
static class Auth {
private String username;
private String password;
}
but it throw a exception:
[cn.gitbug.test.TypeClass$Auth@7921b0a2, cn.gitbug.test.TypeClass$Auth@174d20a]
a1 class: class cn.gitbug.test.TypeClass$Auth
[{username=abc, password=abc}, {username=abc1, password=abc1}]
Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to cn.gitbug.test.TypeClass$Auth
at cn.gitbug.test.TypeClass.main(TypeClass.java:22)
so how can I write the execute()
method?
Upvotes: 2
Views: 5196
Reputation: 607
my solution suggestion
public static <T> List<T> execute(String json, Class<T> clazz) {
Type type = TypeToken.getParameterized(List.class,clazz).getType();
return new Gson().fromJson(json, type);
}
and use
List<Auth> auths = deserialize(json, Auth.class);
Upvotes: 3
Reputation: 6914
public static <T> T execute(String s) throws SecurityException {
return new Gson().fromJson(s, new TypeToken<T>(){}.getType());
}
This will not work because T
is not bound and therefore the erasure type is Object
(which is deserialized as Map
).
The examples in the Gson documentation and the code above work because there the generic type argument is known at compile time and therefore the class will have the expected erasure type:
new TypeToken<List<Auth>>(){}.getType()
Gson 2.8.0 (released in 2016) added TypeToken.getParameterized(...)
. This allows you to dynamically create TypeToken
s for generic classes, but you still have to manually specify the generic type parameters.
A method which accepts the JSON string as only parameter (like your execute
) and then determines the type on its own is not possible because information about the generic type parameter T
is not available at runtime.
Upvotes: 1