gpt4 book ai didi

android - Retrofit 2.0 处理 json 响应中的错误

转载 作者:太空狗 更新时间:2023-10-29 14:50:20 27 4
gpt4 key购买 nike

我正在研究 Retrofit 2.0(非常棒)来处理 API 响应。当 API 成功响应时一切正常,我从 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 回答错误时(还有来自 header 的代码 200),我得到这个:

{
"error":
{
"code":200
"type":"OAuth_exception",
"message":"You need an access token to get an user",
}
}

问题是 retrofit “响应”仍然成功并且 errorBody 为空

所以在这里,我会把它转换成一个 RestError POJO(下面)并在调用 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;
}
}

有解决办法吗?

更新:

我在 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() 获取它并且似乎完成了工作

你在想什么?

最佳答案

您可以从某个 Response 类扩展所有 POJO,该类将包含字段 RestError error。然后你可以制作一些 isSuccessful 方法,它会检查 error 字段是否为 null 并正确处理它。

关于android - Retrofit 2.0 处理 json 响应中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36035831/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com