我正在處理API響應的Retrofit 2.0(這很棒)。 一切運作良好時API的答案與成功,我返回轉換對象從JSON響應Retrofit 2.0在json響應中處理錯誤
這裏的請求的示例希望:
ServiceAPI.getUser(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
User user = response.body(); // user is my POJO
}
@Override
public void onFailure(Call<User> call, final Throwable t) {
Log.e(TAG, "Error: " + t.getMessage())
}
});
當反應完成後,我回到了POJO(這是我的主要目的),而不是json來解析以避免樣板化。
所以在這裏我的代碼來處理這個問題:
// the interface to handle calls
protected interface ServiceAPI {
@GET("/user/{userId}")
Call<User> getUser(@Path("userId") String userId);
}
// the GSON part for converting data
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new ItemTypeAdapterFactory())
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
// an interceptor to log requests responses
OkHttpClient okClient = new OkHttpClient.Builder()
.addInterceptor(new LogJsonInterceptor())
.build();
// the retrofit builder
retrofit = new Retrofit.Builder()
.baseUrl(mBaseUrl)
.client(okClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
// the interceptor to log requests
public static class LogJsonInterceptor implements Interceptor {
@Override
public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
okhttp3.Response response = chain.proceed(request);
String rawJson = response.body().string();
Log.d(TAG, rawJson);
// Re-create the response before returning it because body can be read only once
return response.newBuilder().body(ResponseBody.create(response.body().contentType(), rawJson)).build();
}
}
// here the magic to handle json response and get data from "data" json key
public static class ItemTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(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);
}
private RestError error;
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("data")) {
jsonElement = jsonObject.get("data");
}
}
return delegate.fromJsonTree(jsonElement);
}
}.nullSafe();
}
}
// here the method to call from an activity for example to get an User
public static void getUser(final String userId, final Callback<User> callback) {
serviceAPI.getUser(userId).enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
callback.onResponse(call, response);
}
@Override
public void onFailure(Call<User> call, Throwable t) {
callback.onFailure(call, t);
}
});
}
// here the call from the Activity
ServiceAPI.getUser(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
User user = response.body();
}
@Override
public void onFailure(Call<User> call, final Throwable t) {
Log.e(TAG, "Error: " + t.getMessage())
}
});
// when API answers with success (code 200 from headers)
{
"data":
{
"id":1,
"name":"myname",
"email":"myemail"
}
}
,是因爲我從「數據」應對一切運作良好這裏和反應轉化成我的POJO
問題: 但是當API解答錯誤(也用頭文件中的代碼200),我得到這個:
{
"error":
{
"code":200
"type":"OAuth_exception",
"message":"You need an access token to get an user",
}
}
問題是改造「迴應」是仍然全成和errorBody爲空
所以在這裏,我會打電話的getUser方法
public class RestError {
private int code;
private String message;
private String type;
public RestError(int code, String message, String type) {
this.code = code;
this.message = message;
this.type = type;
}
}
時,將其轉換成RestError POJO(下圖),並把它裏面調用
任何想法解決這個問題?
UPDATE:
我加入這個在ItemTypeAdatperFactory
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("data")) {
jsonElement = jsonObject.get("data");
} else if (jsonObject.has("error")) {
jsonElement = jsonObject.get("error");
TypeAdapter<RestError> restErrorTypeAdapter = gson.getAdapter(RestError.class);
RestError error = restErrorTypeAdapter.fromJsonTree(jsonElement);
return (T) error;
}
}
return delegate.fromJsonTree(jsonElement);
}
我開了這樣一個自定義的回調:
public abstract static class CustomCallback<T> implements Callback<T> {
public abstract void onError(RestError error);
public abstract void onSuccess(T body);
@Override
public void onResponse(Call<T> call, Response<T> response) {
if(response.body() instanceof RestError) {
onError((RestError) response.body());
} else {
onSuccess(response.body());
}
}
@Override
public void onFailure(Call<T> call, Throwable t) {
Log.e(TAG, t.toString());
}
}
所以,現在的電話是如何:
ServiceAPI.getUser(new ServiceAPI.CustomCallback<User>() {
@Override
public void onError(RestError error) {
Log.e(TAG, error.toString());
}
@Override
public void onSuccess(User body) {
Log.d(TAG, body.toString());
User user = body;
}
@Override
public void onFailure(Call<User> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
因此,現在當發生錯誤時,我從onError()獲得它,否則onSuccess(),似乎做的工作
你怎麼看?
其實我有同樣的問題,我能得到響應如果它是200.But我想要的是從202獲得的東西。因此,對於200響應,我們已經創建了一個SuccessResponse GSON類。而對於202類,我還創建了另一個類,取決於JSON響應。 我無法同時使用兩者。我嘗試了Extending also.But沒有他們works.Any建議嗎? –