首页 > 解决方案 > 如何在 gson typeToken 中使用泛型类型?

问题描述

我想在 gson TypeToken 中使用泛型类型,如下所示:

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

但它抛出一个异常:

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

那么我该如何编写execute()方法呢?

标签: genericsserializationgsontypetoken

解决方案


public static <T> T execute(String s) throws SecurityException {
    return new Gson().fromJson(s, new TypeToken<T>(){}.getType());
}

这将不起作用,因为T未绑定,因此擦除类型为Object(反序列化为Map)。

Gson 文档中的示例和上面的代码有效,因为泛型类型参数在编译时是已知的,因此该类将具有预期的擦除类型:

new TypeToken<List<Auth>>(){}.getType()

添加了 Gson 2.8.0(2016 年发布)TypeToken.getParameterized(...)。这允许您TypeToken为泛型类动态创建 s,但您仍然必须手动指定泛型类型参数。

接受 JSON 字符串作为唯一参数(如您的execute)然后自行确定类型的方法是不可能的,因为有关泛型类型参数T的信息在运行时不可用。


推荐阅读