如何为 Gson 的 TypeToken 添加泛型类型?

How do I put generic type for Gson's TypeToken?

编辑 经过一段时间的试验,我知道我的问题是。我无法将泛型类型放入 TypeToken (Type type = new TypeToken<CustomResponse<T>>(){}.getType();) 中。当我将 T 更改为 POJOA 时,我可以 运行 我的应用程序很好地将 json 反序列化为 POJOA,但不能反序列化为 POJOBPOJOC.

如何将通用类型放入 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

您应该为不同的响应类型(POJOAPOJOBPOJOC)编写三个不同的反序列化器,或者编写一个通用的反序列化器。这样的事情应该有效:

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