如何将泛型类型为GSON的TypeToken? [英] How do I put generic type for Gson's TypeToken?

查看:257
本文介绍了如何将泛型类型为GSON的TypeToken?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

修改经历过了一段时间后,我知道我的问题是。我不能把泛型类型在 TypeToken 类型类型=新TypeToken< CustomResponse< T>>(){}的getType()。 )。当我更改 T POJOA ,我可以运行我的应用程序就好了反序列化JSON到 POJOA ,但不进 POJOB POJOC

EDIT After experimenting for a while, I know my problem is. I can't put generic type inside TypeToken (Type type = new TypeToken<CustomResponse<T>>(){}.getType();). When I change T into POJOA, I can run my app just fine to deserialize json into POJOA, but not into POJOB and POJOC.

我如何把泛型类型为TypeToken?或者说,是否有可能做这样的事情:

How do I put generic type into TypeToken? Or, is it possible to do something like this:

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

previous问题:?使用参数化类型时,为什么 parseNetworkResponse 返回任何

Previous Question: Why do parseNetworkResponse return nothing when using parametrized type?

我怀疑的错误是在收益率(响应&LT; T&GT;)Response.success(gson.fromJson(JSON,typeOfT),HttpHeaderParser.parseCacheHeaders(响应)); 的一部分,因为它可以打印 Log.d(CustomRequest,JSON); 上previous线。 (请查看我GsonRequest

I suspect the error is in return (Response<T>) Response.success(gson.fromJson(json, typeOfT), HttpHeaderParser.parseCacheHeaders(response)); part, because it could print Log.d("CustomRequest", json); on previous line. (please look at My 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响应就好了。

so that means I get the json response just fine.

问题是收益率(响应&LT; T&GT;)Response.success(gson.fromJson(JSON,typeOfT),HttpHeaderParser.parseCacheHeaders(响应));

时转换为时出错(响应&LT; T&GT;)

或者是它 gson.fromJson错误(JSON,typeOfT)

推荐答案

您必须指定键入明确。有一个在Java中,类型擦除这基本上意味着,在运行时都 T 实例都替换为对象

You have to specify the Type explicitly. There's type erasure in Java, which basically means that at runtime all instances of T are replaced with Object.

您应该要么写不同的响应类型的三种不同的解串器( POJOA POJOB POJOC ),或者写一个通用的。像这样的东西应该工作:

You should either write three different deserializers for different response types(POJOA, POJOB, POJOC) or write a generic one. Something like this should work:

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

这篇关于如何将泛型类型为GSON的TypeToken?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆