Auto-Value-Gson:泛型 - java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType

时间:2017-01-29 12:00:43

标签: java android gson retrofit auto-value

我遇到auto-value-gson与泛型有关的问题 不幸的是,它无法为我的Response类创建适配器。

Response.java

@AutoValue
public abstract class Response<T> {

    @SerializedName(value="client", alternate={"device", "..."})
    public abstract T getObject();

    @SerializedName("s")
    public abstract boolean isSuccessful();

    @SerializedName("err")
    public abstract String getErrorMessage();


    public static <T> Builder<T> builder() {
        return new $AutoValue_Response.Builder();
    }

    public static <T> TypeAdapter<Response<T>> typeAdapter(Gson gson,
                                        TypeToken<? extends Response<T>> typeToken) {

        return new AutoValue_Response.GsonTypeAdapter(gson, typeToken);
    }

    @AutoValue.Builder
    public abstract static class Builder<T> {
        public abstract Builder<T> setObject(T value);
        public abstract Builder<T> setSuccessful(boolean value);
        public abstract Builder<T> setErrorMessage(String value);
        public abstract Response<T> build();
    }
} 

Client.java

 @AutoValue
 public abstract class Client {


    @SerializedName("id")
    public abstract int getId();

    @SerializedName("loginId")
    public abstract int getLoginId();

    public static Builder builder() {
        return new $AutoValue_Client.Builder();
    }

    public static TypeAdapter<Client> typeAdapter(Gson gson) {
        return new AutoValue_Client.GsonTypeAdapter(gson);
    }

    @AutoValue.Builder
    public abstract static class Builder {
        public abstract Builder setId(int value);
        public abstract Builder setLoginId(int value);
        public abstract Client build();
    }
}

EntityTypeAdapterFactory.java

@GsonTypeAdapterFactory
public abstract class EntityTypeAdapterFactory implements TypeAdapterFactory {

    public static EntityTypeAdapterFactory create() {
        return new AutoValueGson_EntityTypeAdapterFactory();
    }

}

Gson registerTypeAdapterFactory:

@Provides
@Singleton
Gson provideGson() {
    GsonBuilder gsonBuilder = new GsonBuilder();

    gsonBuilder.registerTypeAdapterFactory(EntityTypeAdapterFactory.create());

    return gsonBuilder.create();
}

堆栈跟踪:

    java.lang.IllegalArgumentException: Unable to create converter for class ...response.Response
         for method IClientNetDataService.loginClient
        at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:720)
        at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:706)
        at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:167)
        at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:166)
        at retrofit2.Retrofit$1.invoke(Retrofit.java:145)
        at java.lang.reflect.Proxy.invoke(Proxy.java:393)
        at $Proxy0.loginClient(Unknown Source)
        at ...data.client.net.ClientNetDataSource.loginClient(ClientNetDataSource.java:42)
        at ...data.client.ClientDataRepository.loginClient(ClientDataRepository.java:31)
        at ...domain.login.LoginClientUseCase.lambda$loginClient$0(LoginClientUseCase.java:55)
        at ...domain.login.LoginClientUseCase$$Lambda$1.subscribe(Unknown Source)
        at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:72)
        at io.reactivex.Flowable.subscribe(Flowable.java:12885)
        at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
        at java.lang.Thread.run(Thread.java:818)
     Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
        at ...data.response.AutoValue_Response$GsonTypeAdapter.<init>(AutoValue_Response.java:29)
        at ...data.response.Response.typeAdapter(Response.java:29)
        at ...data.AutoValueGson_EntityTypeAdapterFactory.create(AutoValueGson_EntityTypeAdapterFactory.java:22)
        at com.google.gson.Gson.getAdapter(Gson.java:423)
        at retrofit2.converter.gson.GsonConverterFactory.responseBodyConverter(GsonConverterFactory.java:63)
        at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:325)
        at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:308)
        at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:704)
        ... 19 more
      : java.lang.IllegalArgumentException: Unable to create converter for class ...response.Response
         for method IClientNetDataService.loginClient
        at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:720)
        at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:706)
        at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:167)
        at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:166)
        at retrofit2.Retrofit$1.invoke(Retrofit.java:145)
        at java.lang.reflect.Proxy.invoke(Proxy.java:393)
        at $Proxy0.loginClient(Unknown Source)
        at ...data.client.net.ClientNetDataSource.loginClient(ClientNetDataSource.java:42)
        at ...data.client.ClientDataRepository.loginClient(ClientDataRepository.java:31)
        at ...domain.login.LoginClientUseCase.lambda$loginClient$0(LoginClientUseCase.java:55)
        at ...domain.login.LoginClientUseCase$$Lambda$1.subscribe(Unknown Source)
        at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:72)
        at io.reactivex.Flowable.subscribe(Flowable.java:12885)
        at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.r
     un(FlowableSubscribeOn.java:82)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:59)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:51)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
        at java.lang.Thread.run(Thread.java:818)
     Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
        at ...data.response.AutoValue_Response$GsonTypeAdapter.<init>(AutoValue_Response.java:29)
        at ...data.response.Response.typeAdapter(Response.java:29)
        at ...data.AutoValueGson_EntityTypeAdapterFactory.create(AutoValueGson_EntityTypeAdapterFactory.java:22)
        at com.google.gson.Gson.getAdapter(Gson.java:423)
        at retrofit2.converter.gson.GsonConverterFactory.responseBodyConverter(GsonConverterFactory.java:63)
        at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:325)
        at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:308)
        at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:704)
        ... 19 more

我不确定但是我是否必须创建一个自定义的TypeAdapter / TypeAdapterFactory / JsonDeserializer并为我想在Response中使用的每个类注册它?

我感谢任何帮助。

修改

生成AutoValue_Response.java:

final class AutoValue_Response<T> extends $AutoValue_Response<T> {
  AutoValue_Response(T object, boolean successful, String errorMessage) {
    super(object, successful, errorMessage);
  }

  public static final class GsonTypeAdapter<T> extends TypeAdapter<Response<T>> {
    private final TypeAdapter<T> objectAdapter;
    private final TypeAdapter<Boolean> successfulAdapter;
    private final TypeAdapter<String> errorMessageAdapter;
    private T defaultObject = null;
    private boolean defaultSuccessful = false;
    private String defaultErrorMessage = null;
    public GsonTypeAdapter(Gson gson, TypeToken<? extends Response<T>> typeToken) {
      ParameterizedType type = (ParameterizedType) typeToken.getType();
      Type[] typeArgs = type.getActualTypeArguments();
      this.objectAdapter = (TypeAdapter<T>) gson.getAdapter(TypeToken.get(typeArgs[0]));
      this.successfulAdapter = gson.getAdapter(Boolean.class);
      this.errorMessageAdapter = gson.getAdapter(String.class);
    }
    public GsonTypeAdapter setDefaultObject(T defaultObject) {
      this.defaultObject = defaultObject;
      return this;
    }
    public GsonTypeAdapter setDefaultSuccessful(boolean defaultSuccessful) {
      this.defaultSuccessful = defaultSuccessful;
      return this;
    }
    public GsonTypeAdapter setDefaultErrorMessage(String defaultErrorMessage) {
      this.defaultErrorMessage = defaultErrorMessage;
      return this;
    }
    @Override
    public void write(JsonWriter jsonWriter, Response<T> object) throws IOException {
      if (object == null) {
        jsonWriter.nullValue();
        return;
      }
      jsonWriter.beginObject();
      jsonWriter.name("client");
      objectAdapter.write(jsonWriter, object.getObject());
      jsonWriter.name("s");
      successfulAdapter.write(jsonWriter, object.isSuccessful());
      jsonWriter.name("err");
      errorMessageAdapter.write(jsonWriter, object.getErrorMessage());
      jsonWriter.endObject();
    }
    @Override
    public Response<T> read(JsonReader jsonReader) throws IOException {
      if (jsonReader.peek() == JsonToken.NULL) {
        jsonReader.nextNull();
        return null;
      }
      jsonReader.beginObject();
      T object = this.defaultObject;
      boolean successful = this.defaultSuccessful;
      String errorMessage = this.defaultErrorMessage;
      while (jsonReader.hasNext()) {
        String _name = jsonReader.nextName();
        switch (_name) {
          case "device":
          case "client": {
            object = objectAdapter.read(jsonReader);
            break;
          }
          case "s": {
            successful = successfulAdapter.read(jsonReader);
            break;
          }
          case "err": {
            errorMessage = errorMessageAdapter.read(jsonReader);
            break;
          }
          default: {
            jsonReader.skipValue();
          }
        }
      }
      jsonReader.endObject();
      return new AutoValue_Response<>(object, successful, errorMessage);
    }
  }
}

0 个答案:

没有答案