如何为 Gson 的 TypeToken 添加泛型类型?
How do I put generic type for Gson's TypeToken?
编辑 经过一段时间的试验,我知道我的问题是。我无法将泛型类型放入 TypeToken
(Type type = new TypeToken<CustomResponse<T>>(){}.getType();
) 中。当我将 T
更改为 POJOA
时,我可以 运行 我的应用程序很好地将 json 反序列化为 POJOA
,但不能反序列化为 POJOB
和 POJOC
.
如何将通用类型放入 TypeToken?或者,是否可以这样做:
if (T == POJOA) {
Type type = new TypeToken<CustomResponse<POJOA>>(){}.getType();
} else if (T == POJOB) {
Type type = new TypeToken<CustomResponse<POJOB>>(){}.getType();
} else if (T == POJOC) {
Type type = new TypeToken<CustomResponse<POJOC>>(){}.getType();
};
上一个问题:为什么在使用参数化类型时 parseNetworkResponse
return 什么都不做?
我怀疑错误在 return (Response<T>) Response.success(gson.fromJson(json, typeOfT), HttpHeaderParser.parseCacheHeaders(response));
部分,因为它可以在前一行打印 Log.d("CustomRequest", json);
。 (请看我的GsonRequest)
我的POJO
public class CustomResponse<T> {
T response;
public CustomResponse(T response) {
this.response = response;
}
public T getResponse() {
return response;
}
}
我的自定义解串器
public class POJOADeserializer implements JsonDeserializer<CustomResponse<POJOA>> {
@Override
public CustomResponse<POJOA> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//some deserializing thing
return new CustomResponse<POJOA>();
}
}
public class POJOBDeserializer implements JsonDeserializer<CustomResponse<POJOB>> {
@Override
public CustomResponse<POJOB> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//some deserializing thing
return new CustomResponse<POJOB>();
}
}
public class POJOCDeserializer implements JsonDeserializer<CustomResponse<POJOC>> {
@Override
public CustomResponse<POJOC> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//some deserializing thing
return new CustomResponse<POJOC>();
}
}
我的 GsonRequest
public class CustomRequest<T> extends JsonRequest<T> {
private final Gson gson;
private final Type typeOfT
private final Response.Listener<T> listener;
public CustomRequest(int method,
String url,
Type typeOfT,
JSONObject params,
Response.Listener<T> listener,
Response.ErrorListener errorListener) {
super(method, url, params.toString(), listener, errorListener);
this.typeOfT = typeOfT;
this.listener = listener;
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOA>>(){}.getType(), new POJOADeserializer());
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOB>>(){}.getType(), new POJOBDeserializer());
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOC>>(){}.getType(), new POJOCDeserializer());
this.gson = gsonBuilder.create();
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
Log.d("CustomRequest", json);
return (Response<T>) Response.success(gson.fromJson(json, typeOfT), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
实际调用
public <T> void get(String url,
Response.Listener<CustomResponse<T>> listener,
Response.ErrorListener errorListener) {
Type type = new TypeToken<CustomResponse<T>>(){}.getType();
CustomRequest<CustomResponse<T>> request = new CustomRequest<>(Request.Method.GET, url, type, null, listener, errorListener);
Volley.newRequestQueue(context.getApplicationContext()).add(request);
}
public void getResponse() {
String url = //some url;
get(url, new Response.Listener<CustomResponse<POJOA>>() {
@Override
public void onResponse(CustomResponse<POJOA> response) {
//do something
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//do something
}
});
}
我可以打印 Log.d("CustomRequest", json);
所以这意味着我得到 json 响应就好了。
问题是return (Response<T>) Response.success(gson.fromJson(json, typeOfT), HttpHeaderParser.parseCacheHeaders(response));
。
转换为(Response<T>)
时是否出错?
或者是 gson.fromJson(json, typeOfT)
上的错误
您必须明确指定 Type
。 Java 中有 type erasure,这基本上意味着在运行时 T
的所有实例都被替换为 Object
。
您应该为不同的响应类型(POJOA
、POJOB
、POJOC
)编写三个不同的反序列化器,或者编写一个通用的反序列化器。这样的事情应该有效:
public class GenericConverter implements JsonDeserializer<CustomResponse<?>> {
private Type typeOfResponse;
public GenericConverter(Type typeOfResponse) {
this.typeOfResponse = typeOfResponse;
}
public CustomResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) {
CustomResponse response = new CustomResponse();
response.setResponse(ctx.deserialize(json.getAsJsonObject().get("response"), typeOfResponse));
return response;
}
}
并适当注册:
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOA>>(){}.getType(),
new GenericConverter(POJOA.class));
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOB>>(){}.getType(),
new GenericConverter(POJOB.class));
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOC>>(){}.getType(),
new GenericConverter(POJOC.class));
编辑 经过一段时间的试验,我知道我的问题是。我无法将泛型类型放入 TypeToken
(Type type = new TypeToken<CustomResponse<T>>(){}.getType();
) 中。当我将 T
更改为 POJOA
时,我可以 运行 我的应用程序很好地将 json 反序列化为 POJOA
,但不能反序列化为 POJOB
和 POJOC
.
如何将通用类型放入 TypeToken?或者,是否可以这样做:
if (T == POJOA) {
Type type = new TypeToken<CustomResponse<POJOA>>(){}.getType();
} else if (T == POJOB) {
Type type = new TypeToken<CustomResponse<POJOB>>(){}.getType();
} else if (T == POJOC) {
Type type = new TypeToken<CustomResponse<POJOC>>(){}.getType();
};
上一个问题:为什么在使用参数化类型时 parseNetworkResponse
return 什么都不做?
我怀疑错误在 return (Response<T>) Response.success(gson.fromJson(json, typeOfT), HttpHeaderParser.parseCacheHeaders(response));
部分,因为它可以在前一行打印 Log.d("CustomRequest", json);
。 (请看我的GsonRequest)
我的POJO
public class CustomResponse<T> {
T response;
public CustomResponse(T response) {
this.response = response;
}
public T getResponse() {
return response;
}
}
我的自定义解串器
public class POJOADeserializer implements JsonDeserializer<CustomResponse<POJOA>> {
@Override
public CustomResponse<POJOA> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//some deserializing thing
return new CustomResponse<POJOA>();
}
}
public class POJOBDeserializer implements JsonDeserializer<CustomResponse<POJOB>> {
@Override
public CustomResponse<POJOB> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//some deserializing thing
return new CustomResponse<POJOB>();
}
}
public class POJOCDeserializer implements JsonDeserializer<CustomResponse<POJOC>> {
@Override
public CustomResponse<POJOC> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
//some deserializing thing
return new CustomResponse<POJOC>();
}
}
我的 GsonRequest
public class CustomRequest<T> extends JsonRequest<T> {
private final Gson gson;
private final Type typeOfT
private final Response.Listener<T> listener;
public CustomRequest(int method,
String url,
Type typeOfT,
JSONObject params,
Response.Listener<T> listener,
Response.ErrorListener errorListener) {
super(method, url, params.toString(), listener, errorListener);
this.typeOfT = typeOfT;
this.listener = listener;
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOA>>(){}.getType(), new POJOADeserializer());
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOB>>(){}.getType(), new POJOBDeserializer());
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOC>>(){}.getType(), new POJOCDeserializer());
this.gson = gsonBuilder.create();
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
Log.d("CustomRequest", json);
return (Response<T>) Response.success(gson.fromJson(json, typeOfT), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
实际调用
public <T> void get(String url,
Response.Listener<CustomResponse<T>> listener,
Response.ErrorListener errorListener) {
Type type = new TypeToken<CustomResponse<T>>(){}.getType();
CustomRequest<CustomResponse<T>> request = new CustomRequest<>(Request.Method.GET, url, type, null, listener, errorListener);
Volley.newRequestQueue(context.getApplicationContext()).add(request);
}
public void getResponse() {
String url = //some url;
get(url, new Response.Listener<CustomResponse<POJOA>>() {
@Override
public void onResponse(CustomResponse<POJOA> response) {
//do something
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//do something
}
});
}
我可以打印 Log.d("CustomRequest", json);
所以这意味着我得到 json 响应就好了。
问题是return (Response<T>) Response.success(gson.fromJson(json, typeOfT), HttpHeaderParser.parseCacheHeaders(response));
。
转换为(Response<T>)
时是否出错?
或者是 gson.fromJson(json, typeOfT)
您必须明确指定 Type
。 Java 中有 type erasure,这基本上意味着在运行时 T
的所有实例都被替换为 Object
。
您应该为不同的响应类型(POJOA
、POJOB
、POJOC
)编写三个不同的反序列化器,或者编写一个通用的反序列化器。这样的事情应该有效:
public class GenericConverter implements JsonDeserializer<CustomResponse<?>> {
private Type typeOfResponse;
public GenericConverter(Type typeOfResponse) {
this.typeOfResponse = typeOfResponse;
}
public CustomResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) {
CustomResponse response = new CustomResponse();
response.setResponse(ctx.deserialize(json.getAsJsonObject().get("response"), typeOfResponse));
return response;
}
}
并适当注册:
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOA>>(){}.getType(),
new GenericConverter(POJOA.class));
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOB>>(){}.getType(),
new GenericConverter(POJOB.class));
gsonBuilder.registerTypeAdapter(new TypeToken<CustomResponse<POJOC>>(){}.getType(),
new GenericConverter(POJOC.class));