具有动态 ArrayList 项类型的 Gson 类型

2022-08-31 11:29:54

我有这个代码:

Type typeOfObjectsList = new TypeToken<ArrayList<myClass>>() {}.getType();
List<myClass> objectsList = new Gson().fromJson(json, typeOfObjectsList);

它将 JSON 字符串转换为对象的 a。但是现在我想用一个动态类型(不仅仅是)来定义它,在运行时定义。ListArrayListmyClass

ArrayList 的项类型将使用反射进行定义。

我试过这个:

    private <T> Type setModelAndGetCorrespondingList2(Class<T> type) {
        Type typeOfObjectsListNew = new TypeToken<ArrayList<T>>() {}.getType();
        return typeOfObjectsListNew;
    }

但它不起作用。这是例外:

java.sql.SQLException: Fail to convert to internal representation: {....my json....}

答案 1

从Gson 2.8.0开始,你可以使用TypeToken#getParameterized(Type rawType, Type...typeArguments) 来创建 ,然后应该做这个把戏。TypeTokengetType()

例如:

TypeToken.getParameterized(ArrayList.class, myClass).getType()

答案 2

您建议的语法无效。以下

new TypeToken<ArrayList<Class.forName(MyClass)>>

无效,因为您尝试传递需要类型名称的方法调用。

以下

new TypeToken<ArrayList<T>>() 

由于泛型(类型擦除)和反射的工作方式,因此是不可能的。整个黑客工作,因为以下行为TypeTokenClass#getGenericSuperclass()

返回 Type,该类型表示由此类表示的实体(类、接口、基元类型或 void)的直接超类。

如果超类是参数化类型,则返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。

换句话说,如果它看到 ,那就是它将返回,您将无法提取类型变量本来具有的编译时值。ArrayList<T>ParameterizedTypeT

Type并且都是接口。您可以提供自己的实现的实例(定义一个实现接口并重写其方法的类),或者使用 TypeToken 在其最新版本中提供的有用工厂方法之一。例如ParameterizedType

private Type setModelAndGetCorrespondingList2(Class<?> typeArgument) {
    return TypeToken.getParameterized(ArrayList.class, typeArgument).getType();
}