[英]Get Type of ParameterizedType from generic
I cannot understand fully how reflect works, so I'm having some trouble trying to register a custom type adapter for my GsonBuilder
. 我无法完全理解反射的工作原理,因此尝试为
GsonBuilder
注册自定义类型适配器时遇到了一些麻烦。
I need to register a type adapter for a List<Something>
type. 我需要为
List<Something>
类型注册类型适配器。
This is a working code: 这是一个工作代码:
gsonBuilder.registerTypeAdapter(
new TypeToken<List<MyClass>>() { }.getType(), new ListDeserializer(MyClass.class)
);
The thing is that I have a lot of classes to register my type adapter, and I have a ListDeserializer
and SingleDeserializer
adapters. 问题是我有很多类来注册我的类型适配器,并且我有一个
ListDeserializer
和SingleDeserializer
适配器。
I'm trying to go generic so I just call a function, pass my GsonBuilder
and class, and there you go. 我试图变得通用,所以我只调用一个函数,传递我的
GsonBuilder
和类,然后就可以了。
Here is my try: 这是我的尝试:
private static <T> void registerTypeAdapter(GsonBuilder gsonBuilder, T clazz) {
gsonBuilder.registerTypeAdapter(clazz.getClass(), new SingleDeserializer(clazz.getClass()));
gsonBuilder.registerTypeAdapter(
new TypeToken<List<T>>() {
}.getType(), new ListDeserializer(clazz.getClass())
);
}
It doesn't work for my ListDeserializer
. 它不适用于
ListDeserializer
。 My guess is that since T
is a generic parameterized type of List
, it cannot detect it at runtime. 我的猜测是,由于
T
是List
的通用参数化类型,因此它无法在运行时检测到它。
Any suggestions? 有什么建议么?
Yep you can't use new TypeToken<List<T>>() {}.getType()
at runtime, because of generics type erasure . 是的,由于泛型类型的擦除 ,您不能在运行时使用
new TypeToken<List<T>>() {}.getType()
。 List<T>
is just List<Object>
at runtime. List<T>
List<Object>
在运行时只是List<Object>
。 but what you could do is to create ParameterizedType
and use something like this: 但是您可以做的是创建
ParameterizedType
并使用如下代码:
Type type = ParameterizedTypeImpl.make(List.class, new Type[]{clazz.getClass()}, null);
gsonBuilder.registerTypeAdapter(type, new ListDeserializer(clazz.getClass()) );
But do you really need genericness? 但是,您真的需要泛型吗? You could do
你可以做
private static void registerTypeAdapter2(GsonBuilder gsonBuilder, Class<?> clazz) {
gsonBuilder.registerTypeAdapter(clazz, new SingleDeserializer());
Type type = ParameterizedTypeImpl.make(List.class, new Type[]{clazz}, null);
gsonBuilder.registerTypeAdapter(type, new ListDeserializer());
}
Here is demo: 这是演示:
import com.google.gson.*;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) throws Exception {
GsonBuilder gb = new GsonBuilder();
registerTypeAdapter(gb, MyClass.class);
Gson gson = gb.create();
List data = new ArrayList<>();
data.add(new MyClass("Bob"));
data.add(new MyClass("Alice"));
String listString = gson.toJson(data);
String soloString = gson.toJson(new MyClass("Test"));
Object resultList = gson.fromJson(listString, new TypeToken<List<MyClass>>() {}.getType());
Object resultSolo = gson.fromJson(soloString, MyClass.class);
System.out.println("RESULT:");
System.out.println("FROM " + listString +" TO "+ resultList);
System.out.println("FROM " + soloString +" TO "+ resultSolo);
}
private static void registerTypeAdapter(GsonBuilder gsonBuilder, Class<?> clazz) {
gsonBuilder.registerTypeAdapter(clazz, new SingleDeserializer());
Type type = ParameterizedTypeImpl.make(List.class, new Type[]{clazz}, null);
gsonBuilder.registerTypeAdapter(type, new ListDeserializer());
}
private static class ListDeserializer implements JsonDeserializer {
private static Gson gson = new Gson();
@Override
public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
System.out.println("Used ListDeserializer: Type " + typeOfT);
Type t = (typeOfT instanceof ParameterizedType) ?
((ParameterizedType) typeOfT).getActualTypeArguments()[0] :
Object.class;
Type type = ParameterizedTypeImpl.make(List.class, new Type[]{t}, null);
List list = gson.fromJson(json, type);
return list;
}
}
private static class SingleDeserializer implements JsonDeserializer {
private static Gson gson = new Gson();
@Override
public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
System.out.println("Used SingleDeserializer: Type " + typeOfT);
return gson.fromJson(json, typeOfT);
}
}
public static class MyClass {
@SerializedName("name")
private String name;
public MyClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "MyClass{" +
"name='" + name + '\'' +
'}';
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.