改造多种响应类型 [英] Retrofit multiple response types
问题描述
如何使用Retrofit2解析这两种API响应?
How can I use Retrofit2 to parse these two kinds of API responses?
确定响应(HTTP 200):
Ok response (HTTP 200):
{
"data": {
"foo": "bar"
}
}
错误响应(HTTP 200):
Error response (HTTP 200):
{
"error": {
"foo": "bar"
}
}
我已经阅读了很多SO问题和教程,但是我不知道该怎么做,我已经尝试过:
I've read tons of SO questions and tutorials, but I don't know how to do that, I've tried:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(new ItemTypeAdapterFactory());
Gson gson = gsonBuilder.create();
final Retrofit retrofit = new Retrofit.Builder()
.client(getOkHttpClient())
.baseUrl(Constants.API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
这是我的ItemTypeAdapterFactory:
And this is my ItemTypeAdapterFactory:
class ItemTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
// Data key
if (jsonObject.has(Constants.JSON_KEY_DATA)) {
JsonElement jsonData = jsonObject.get(Constants.JSON_KEY_DATA);
// Primitive
if (jsonData.isJsonPrimitive()) {
jsonElement = jsonData.getAsJsonPrimitive();
}
// JSON object
else if (jsonData.isJsonObject()) {
jsonElement = jsonData;
}
// JSON object array
else if (jsonData.isJsonArray()) {
jsonElement = jsonData.getAsJsonArray();
}
}
}
return delegate.fromJsonTree(jsonElement);
}
}.nullSafe();
}
}
但是现在我不知道在Call:内部的retrofit2接口上要声明的类型:
But now I don't know the type to be declared on retrofit2 interface, inside Call:
@GET("login")
Call<?> login(@Query(Constants.API_PARAM_TOKEN) String token);
能给我指出正确的方向吗?
Could you please point me in the right direction?
推荐答案
在类似的情况下,我曾经使用JsonObject
作为类型,因此您的函数将如下所示:
In a similar case, I once used JsonObject
as type, so your function will look like this:
@GET("login")
Call<?> login(@Query(Constants.API_PARAM_TOKEN) String token);
接下来,当您进行改造调用时,将响应保留为字符串.因此,在您的Java代码中,执行以下操作:
Next, when you make a retrofit call, you keep the response as a string. So, in your java code, do something like this:
Call<JsonObject> call = RetrofitClient.getAPIService().login('YOUR_INPUT');
Data data = null;
Error error = null;
call.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if(response.isSuccessfull()){
String jsonString = response.body().toString();
if(jsonString.contains("data:")){
data = new Gson().fromJson(jsonString,Data.class);
}else{
error = new Gson().fromJson(jsonString,Error.class);
}
}
}
在这里,我使用了Data
和Error
这两个类.它们是POJO.因此,数据可以如下所示:
Here, I have used Data
and Error
these 2 classes. They are the POJOs. So Data can look something like this:
public class Data implements Serializable{
@SerializedName("foo")
@Expose
private Foo foo; // Foo is your desired data type
}
Error
相同.因此,根据您的其余代码,进行必要的更改.祝你好运.
Same goes for Error
. So depending on your rest of the code, make necessary changes. Good luck.
这篇关于改造多种响应类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!