hehe
hehe

Reputation: 387

how to use generic type in gson typeToken?

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

Answers (2)

DEV-Jacol
DEV-Jacol

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

more about link or link

Upvotes: 3

Marcono1234
Marcono1234

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 TypeTokens 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

Related Questions