我在使用 auto-value-gson 和泛型时遇到了问题。
不幸的是,它无法为我的 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();
}
}
客户端.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);
}
}
}