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

时间:2015-04-26 04:14:30

标签: android json gson android-volley

编辑经过一段时间的实验,我知道我的问题是。我不能将通用类型放在TypeTokenType 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 (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)

上的错误

1 个答案:

答案 0 :(得分:0)

您必须明确指定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));