Java类型泛型作为GSON的参数

Java类型泛型作为GSON的参数,java,generics,gson,Java,Generics,Gson,在GSON中获取您要执行的操作的对象列表 Gson gson = new Gson(); Type token = new TypeToken<List<MyType>>(){}.getType(); return gson.fromJson(json, token); Gson-Gson=new-Gson(); Type token=new-TypeToken(){}.getType(); 返回gson.fromJson(json,令牌); 它工作得很好,但我想更进

在GSON中获取您要执行的操作的对象列表

Gson gson = new Gson();
Type token = new TypeToken<List<MyType>>(){}.getType();
return gson.fromJson(json, token);
Gson-Gson=new-Gson();
Type token=new-TypeToken(){}.getType();
返回gson.fromJson(json,令牌);
它工作得很好,但我想更进一步,将MyType参数化,这样我就可以有一个公共函数来解析使用此代码的对象列表

// the common function 
public <T> List<T> fromJSonList(String json, Class<T> type) {
  Gson gson = new Gson();
  Type collectionType = new TypeToken<List<T>>(){}.getType();
  return gson.fromJson(json, collectionType);
}

// the call
List<MyType> myTypes = parser.fromJSonList(jsonString, MyType.class);
//公共函数
来自JSONList的公共列表(字符串json,类类型){
Gson Gson=新的Gson();
Type collectionType=new-TypeToken(){}.getType();
返回gson.fromJson(json,collectionType);
}
//电话
List myTypes=parser.fromJSonList(jsonString,MyType.class);

遗憾的是,返回的是StringMaps数组,而不是类型。T被解释为另一个泛型类型,而不是my类型。有什么解决方法吗?

泛型在编译时工作。超级类型标记之所以有效,是因为(匿名)内部类可以访问其泛型超类(超级接口)的类型参数,而泛型超类(超级接口)又直接存储在字节码元数据中

编译.java源文件后,类型参数
显然会被丢弃。由于在编译时它是未知的,所以它不能存储在字节码中,所以它被擦除,Gson无法读取它

更新

在newacct回答之后,我尝试实现他在选项2中提出的建议,即实现
参数化类型
。代码如下所示(这里是一个基本代码):

即使这项技术可行,而且确实非常聪明(我不知道,也从未想过),这也是最终的成就:

List<Integer> list = new Factory<Integer>()
         .getFromJsonList(text, Integer.class)
List List=新工厂()
.getFromJsonList(文本,整数.class)
而不是

List<Integer> list = new Gson().fromJson(text,
         new TypeToken<List<Integer>>(){}.getType());
List List=new Gson().fromJson(文本,
新的TypeToken(){}.getType());

对我来说,所有这些包装都是无用的,即使我同意
TypeToken
s会让代码看起来很糟糕:p

泛型在编译时工作。超级类型标记之所以有效,是因为(匿名)内部类可以访问其泛型超类(超级接口)的类型参数,而泛型超类(超级接口)又直接存储在字节码元数据中

编译.java源文件后,类型参数
显然会被丢弃。由于在编译时它是未知的,所以它不能存储在字节码中,所以它被擦除,Gson无法读取它

更新

在newacct回答之后,我尝试实现他在选项2中提出的建议,即实现
参数化类型
。代码如下所示(这里是一个基本代码):

即使这项技术可行,而且确实非常聪明(我不知道,也从未想过),这也是最终的成就:

List<Integer> list = new Factory<Integer>()
         .getFromJsonList(text, Integer.class)
List List=新工厂()
.getFromJsonList(文本,整数.class)
而不是

List<Integer> list = new Gson().fromJson(text,
         new TypeToken<List<Integer>>(){}.getType());
List List=new Gson().fromJson(文本,
新的TypeToken(){}.getType());

对我来说,所有这些包装都是无用的,即使我同意
TypeToken
s会让代码看起来很糟糕:p

这已经在前面的问题中得到了回答。基本上有两种选择:

  • 从呼叫站点传入
    类型
    。调用代码将使用
    TypeToken
    或任何构造它的东西
  • 自己构造一个与参数化类型对应的
    类型
    。这将要求您编写一个实现
    ParameterizedType

  • 这已经在前面的问题中得到了回答。基本上有两种选择:

  • 从呼叫站点传入
    类型
    。调用代码将使用
    TypeToken
    或任何构造它的东西
  • 自己构造一个与参数化类型对应的
    类型
    。这将要求您编写一个实现
    ParameterizedType
  • 我进一步采用了这种方法,并对该类进行了泛化,使其适用于每个类A,其中B是一个非参数化类。可能对集合和其他集合有用

        public class GenericOf<X, Y> implements ParameterizedType {
    
        private final Class<X> container;
        private final Class<Y> wrapped;
    
        public GenericOf(Class<X> container, Class<Y> wrapped) {
            this.container = container;
            this.wrapped = wrapped;
        }
    
        public Type[] getActualTypeArguments() {
            return new Type[]{wrapped};
        }
    
        public Type getRawType() {
            return container;
        }
    
        public Type getOwnerType() {
            return null;
        }
    
    }
    
    public类GenericOf实现参数化类型{
    私有最终类容器;
    私人期末班;
    公共GenericOf(类容器,类包装){
    this.container=容器;
    this.wrapped=wrapped;
    }
    公共类型[]getActualTypeArguments(){
    返回新类型[]{wrapped};
    }
    公共类型getRawType(){
    返回容器;
    }
    公共类型getOwnerType(){
    返回null;
    }
    }
    
    我将该方法向前推进了一步,并对该类进行了泛化,使其适用于每个类A,其中B是一个非参数化类。可能对集合和其他集合有用

        public class GenericOf<X, Y> implements ParameterizedType {
    
        private final Class<X> container;
        private final Class<Y> wrapped;
    
        public GenericOf(Class<X> container, Class<Y> wrapped) {
            this.container = container;
            this.wrapped = wrapped;
        }
    
        public Type[] getActualTypeArguments() {
            return new Type[]{wrapped};
        }
    
        public Type getRawType() {
            return container;
        }
    
        public Type getOwnerType() {
            return null;
        }
    
    }
    
    public类GenericOf实现参数化类型{
    私有最终类容器;
    私人期末班;
    公共GenericOf(类容器,类包装){
    this.container=容器;
    this.wrapped=wrapped;
    }
    公共类型[]getActualTypeArguments(){
    返回新类型[]{wrapped};
    }
    公共类型getRawType(){
    返回容器;
    }
    公共类型getOwnerType(){
    返回null;
    }
    }
    
    由于
    gson 2.8.0
    ,您可以使用来创建
    typeToken
    ,然后
    getType()
    应该完成这项任务

    例如:

    TypeToken.getParameterized(List.class, myType).getType();
    

    由于
    gson 2.8.0
    ,您可以使用来创建
    typeToken
    ,然后
    getType()
    应该完成这项任务

    例如:

    TypeToken.getParameterized(List.class, myType).getType();
    
    Kotlin为我提供的“列表”解决方案:

    fun <T: Any> getGsonList(json: String, kclass: KClass<T>) : List<T> {
    
        return getGsonInstance().fromJson<List<T>>(json, ListOfSomething<T>(kclass.java))
    }
    
    
    internal class ListOfSomething<X>(wrapped: Class<X>) : ParameterizedType {
    
        private val wrapped: Class<*>
    
        init {
            this.wrapped = wrapped
        }
    
        override fun getActualTypeArguments(): Array<Type> {
            return arrayOf<Type>(wrapped)
        }
    
        override fun getRawType(): Type {
            return ArrayList::class.java
        }
    
        override fun getOwnerType(): Type? {
            return null
        }
    }
    
    fun getGsonList(json:String,kclass:kclass):列表{
    返回getGsonInstance().fromJson(json,ListOfSomething(kclass.java))
    }
    某些内容的内部类列表(包装:类):ParameteredType{
    私有类:类
    初始化{
    this.wrapped=wrapped
    }
    重写getActualTypeArguments():数组{
    返回阵列(已包装)
    }
    重写getRawType():类型
    
    class GenericGson {
    
        companion object {
            inline fun <reified T : Any> Gson.fromJsonTokenType(jsonString: String): T {
                val type = object : TypeToken<T>() {}.type
                return this.fromJson(jsonString, type)
            }
    
            inline fun <reified T : Any> Gson.fromJsonType(jsonString: String): T = this.fromJson(jsonString, T::class.java)
    
            inline fun <reified T : Any> fromJsonTokenType(jsonString: String): T = Gson().fromJsonTokenType(jsonString)
    
            inline fun <reified T : Any> fromJsonType(jsonString: String): T = Gson().fromJsonType(jsonString)
        }
    }
    
    val arrayList = GenericGson.fromJsonTokenType<ArrayList<Person>>(json)
    
    val places = getPlaces(Array<Place>::class.java)
    
    public <T> List<T> fromJSonList(String json, Class<T> myType) {
        Gson gson = new Gson();
        Type collectionType = TypeToken.getParameterized(List.class, myType).getType();
        return gson.fromJson(json, collectionType);
    }
    
    List<MyType> myTypes = parser.fromJSonList(jsonString, MyType.class);
    
      public static <T> T getObject(String gsonStr) {
            Gson gson = new GsonBuilder()
                    .setLenient()
                    .create();
            Type collectionType = new TypeToken< T>(){}.getType();
            return gson.fromJson(gsonStr,
                    collectionType);
        }
    
    Class1 class1=  getObject(jsonStr);
    
    CustomType type = new CustomType(Map.class, String.class, Integer.class);
    
    class CustomType implements ParameterizedType {
        private final Class<?> container;
        private final Class<?>[] wrapped;
    
        @Contract(pure = true)
        public CustomType(Class<?> container, Class<?>... wrapped) {
            this.container = container;
            this.wrapped = wrapped;
        }
    
        @Override
        public Type[] getActualTypeArguments() {
            return this.wrapped;
        }
    
        @Override
        public Type getRawType() {
            return this.container;
        }
    
        @Override
        public Type getOwnerType() {
            return null;
        }
    }
    
    inline fun <reified T> fromJson(json: String): T {
      return Gson().fromJson(json, object: TypeToken<T>(){}.type)
    }
    
    val myTypes: List<MyType> = fromJson(jsonString);
    
    public <T> List<T> fromJSonList(String json) {
      Gson gson = new Gson();
      Type collectionType = new TypeToken<List<T>>(){}.getType();
      return gson.fromJson(json, collectionType);
    }
    
    //Just call
    List<MyType> myTypes = parser.<MyType>fromJSonList(jsonString);