带有Retrofit 2的多个转换器

我有HATEOAS(HAL)

REST服务,并设法通过下面的代码与之交谈(使用怪异的转换引擎),但是当我尝试合并转换器(stallonestallone2)时,应用程序将始终选择第一个转换器,而不是当然,这会导致错误。

public interface Stallone {

@GET("/discovery")

Call<DiscoveryResponse> discover();

@POST()

Call<LoginResponse> login(@Url String url, @Body LoginRequest secret);

}

public static void main(String... args) throws IOException {

// Initialize a converter for each supported (return) type

final Stallone stallone = new Retrofit.Builder()

.baseUrl(BASE)

.addConverterFactory(HALConverterFactory.create(DiscoveryResponse.class))

.build().create(Stallone.class);

final Stallone stallone2 = new Retrofit.Builder()

.baseUrl(BASE)

.addConverterFactory(HALConverterFactory.create(LoginResponse.class))

.build().create(Stallone.class);

// Follow the HAL links

Response<DiscoveryResponse> response = stallone.discover().execute();

System.out.println(response.code() + " " + response.message());

Assert.assertNotNull(response.body());

String loginPath = response.body().getLogin();

Assert.assertEquals(loginPath, "/login");

// Follow another link

if (loginPath.startsWith("/"))

loginPath = loginPath.substring(1);

Response<LoginResponse> response2 =

stallone2.login(loginPath,

new LoginRequest(AUTH0TOKEN, null)).execute();

System.out.println(response2.code() + " " + response2.message());

Assert.assertNotNull(response2.body());

String setupPath = response2.body().getSetup();

Assert.assertEquals(setupPath, "/setup");

System.out.println("All OK!");

}

public final class HALConverterFactory extends Converter.Factory {

private final Gson gson;

public static HALConverterFactory create(Class<?> type) {

return new HALConverterFactory(type);

}

private HALConverterFactory(Class<?> type) {

if (!HalResource.class.isAssignableFrom(type))

throw new NullPointerException("Type should be a subclass of HalResource");

GsonBuilder builder = new GsonBuilder();

builder.registerTypeAdapter(HalResource.class, new HalSerializer());

builder.registerTypeAdapter(HalResource.class, new HalDeserializer(type));

builder.setExclusionStrategies(new HalExclusionStrategy());

this.gson = builder.create();

}

@Override

public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {

return new HALResponseBodyConverter<>(gson);

}

@Override public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) {

return new GsonRequestBodyConverter<>(gson, type);

}

}

final class HALResponseBodyConverter<T extends HalResource>

implements Converter<ResponseBody, T> {

private final Gson gson;

HALResponseBodyConverter(Gson gson) {

this.gson = gson;

}

@Override public T convert(ResponseBody value) throws IOException {

BufferedSource source = value.source();

try {

String s = source.readString(Charset.forName("UTF-8"));

return (T) gson.fromJson(s, HalResource.class);

} catch (Exception e) {

throw new RuntimeException(e);

} finally {

closeQuietly(source);

}

}

private static void closeQuietly(Closeable closeable) {

if (closeable == null) return;

try {

closeable.close();

} catch (IOException ignored) {

}

}

}

当您尝试像这样缩短上述时间时:

  final Stallone stallone = new Retrofit.Builder()

.baseUrl(BASE)

.addConverterFactory(HALConverterFactory.create(DiscoveryResponse.class))

.addConverterFactory(HALConverterFactory.create(LoginResponse.class))

.build().create(Stallone.class);

您会在该Response<LoginResponse> response2 = ...行得到一个例外:

线程“主”中的异常java.lang.ClassCastException:com.example.retrofit.DiscoveryResponse无法转换为com.example.retrofit.LoginResponse

回答:

如果类型不匹配nullConverter.Factory则需要从中返回。将Class<?>周围保持在一个字段中进行比较。

@Override

public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {

if (!this.type.equals(type)) {

return null;

}

return new HALResponseBodyConverter<>(gson);

}

这将允许使用多个实例,因为每个实例仅适用于其自己的类型。

就是说,但是,您可能仅使用单个转换器并从Type传入的类中拉取类就可以摆脱现实。

@Override

public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {

if (!HALResponse.class.isAssignableFrom(type)) {

return null;

}

// TODO create converter with `type` now that you know what it is...

}

您可以查看回购中的Wire转换器,这是一个完整的示例。

以上是 带有Retrofit 2的多个转换器 的全部内容, 来源链接: utcz.com/qa/409002.html

回到顶部