改造动态 ResponseBody

Retrofit Dynamic ResponseBody

我计划使用 Retrofit 制作一项通用服务 class,

@GET
Call<ResponseBody> makeGetRequest(@Url String url);

@POST
Call<ResponseBody> makePostRequest(@Url String url, @Body RequestBody parameters);

在此代码中,我需要将 (ResponseBody) 作为动态 JSON POJO class 名称传递,例如 LoginRes

举个例子,

Call<LoginRes> // But this class will be dynamic

我将传递 ResponseBody,但 ResponseBody 不知道我想选择哪个 class。

为什么我想要这个因为,在结果之后

gson.fromJson(response, LoginRes.class);

因此,从 Retrofit 获得结果后,我们再次需要转换为 gson.fromJson。

所以我想将动态响应作为 Retrofit 传递,以便它根据我的 pojo 进行响应 class,

我知道当我传递 LoginRes 而不是 ResponseBody 时这工作正常,因为我已经告诉 Response 我们需要 LoginRes 中的响应。

所以如果我通过

Call<LoginRes> // if i pass this way its working fine no need to convert my response i can access my all properties from that LoginRes class directly. 

这是我调用 Web 服务的示例。

Call<ResponseBody> call = apiService.makePostRequest("/Buyer/LoginApp", requestBody);

这就是我调用服务的方式。

如果我对问题的解释不清楚,请告诉我。

等待对此的一些好的回应和建议。

谢谢 马达夫

这有点棘手,但您需要使用带有自定义 GsonBuilder 的自定义 Retrofit Converter Factory,后者使用自定义 JsonDeserializer。

此外,您应该定义一个使用 CustomJsonDeserializer 的接口(CustomResonse 在我的示例中)。这不是必需的,但反序列化器会用于 每个 请求。

public class CustomConverterFactory {

    public static GsonConverterFactory create() {
        return GsonConverterFactory.create(createGsonCustomDeserializer());
    }

    public static Gson createGsonCustomJsonDeserializer() {
        return new GsonBuilder()
            .registerTypeAdapter(CustomResponse.class, new CustomJsonDeserializer())
            .serializeNulls()
            .create();
    }
}

对于解串器:

public class CustomJsonDeserializer implements JsonDeserializer<CustomResponse> {

@Override
public CustomResponse deserialize(final JsonElement json, final Type typeOfT,
        final JsonDeserializationContext context) throws JsonParseException {
    if (json.isJsonObject()) {
        JsonObject jsonObject = json.getAsJsonObject();

        // Here you have to distinguish your class somehow
        // Maybe read some Json field from your response
        if (jsonObject.has("name")) {
            JsonElement classes = jsonObject.get("name");
            ...
            return context.deserialize(json, MyName.class);
        }
        ...
        // Default fallback: Deserialize as a fallback object
        return context.deserialize(json, MyFallback.class);
    } else {
        throw new IllegalStateException();
    }
}

Since so many users given a DOWN VOTE, I have already solved this question by my self,

处理 GET,POST 或像这样的其他方法,

if (methodType.equalsIgnoreCase(CommonConfig.WsMethodType.GET)) {
                apicall = getClient(CommonConfig.WsPrefix).create(ApiInterface.class).makeGetRequest(url + CommonConfig.getQueryString(new Gson().toJson(requestBody)), getAllHeader);
 } else if (methodType.equalsIgnoreCase(CommonConfig.WsMethodType.POST)) {
                apicall = getClient(CommonConfig.WsPrefix).create(ApiInterface.class).makePostRequest(url, RequestBody.create(MediaType.parse("application/json"), new Gson().toJson(requestBody)), getAllHeader);
 }

像这样处理响应。

apicall.enqueue(new Callback<ResponseBody>() {
                                @Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}

 @Override
 public void onFailure(Call<ResponseBody> call, Throwable t) {

}
}

改造代码

private Retrofit getClient(String WsPrefix) {
        //TODO 60 to 30 second at everywhere
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .build();

        retrofit = new Retrofit.Builder()
                .baseUrl(WsPrefix)
                .client(okHttpClient)
                .build();
        return retrofit;
    }

通用接口

interface ApiInterface {

        @GET
        Call<ResponseBody> makeGetRequest(@Url String url, @HeaderMap() Map<String, String> header);

        @POST
        Call<ResponseBody> makePostRequest(@Url String url, @Body RequestBody requestBody, @HeaderMap() Map<String, String> header);
}

ApiCallback

public interface ApiCallback {
      void success(String responseData);
      void failure(String responseData);
}