android - 使用改造 ResponseBody 的自定义消息错误

标签 android json retrofit httpresponse retrofit2

我正在尝试使用 Retrofit 从我的 API 获取错误消息,我尝试做的是以下操作,但我收到导致我的应用程序崩溃的错误,这是错误日志:

    --------- beginning of crash
10-03 16:51:56.776 18801-18801/com.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app, PID: 18801
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
at com.app.rest.ErrorUtils.parseError(ErrorUtils.java:25)
at com.app.MainActivity$1$1.onResponse(MainActivity.java:77)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:746)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37) 
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25) 
at com.app.rest.ErrorUtils.parseError(ErrorUtils.java:25) 
at com.app.MainActivity$1$1.onResponse(MainActivity.java:77) 
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68) 
at android.os.Handler.handleCallback(Handler.java:746) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5443) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 

API 错误信息:

[
  {
    "field": "username",
    "message": "\"Username\" não pode ficar em branco."
  },
  {
    "field": "password",
    "message": "Invalid username or password."
  }
]

ErrorUtils:

public class ErrorUtils {

    public static List<ApiError> parseError(Response<?> response) {

        Converter<ResponseBody, List<ApiError>> converter = ApiClient.getClient()
                .responseBodyConverter(ApiError.class, new Annotation[0]);

        List<ApiError> error;

        try {
            error = converter.convert(response.errorBody());
        } catch (IOException e) {
            e.printStackTrace();
            return (List<ApiError>) new ApiError();
        }

        return error;
    }
}

API错误:

public class ApiError {

    @SerializedName("message")
    private String message;

    public ApiError() {
    }


    public String message() {
        return message;
    }
}

主要 Activity :

 Call<UserResponse> call = apiService.createUser(user);
                    call.enqueue(new Callback<UserResponse>() {
                        @Override
                        public void onResponse(Call<UserResponse> call, Response<UserResponse> response) {
                            int statuscode = response.code();
                            if (statuscode == 200) {
                                Intent mIntent = new Intent(MainActivity.this, NavigationMain.class);
                                startActivity(mIntent);
                                finish();
                            } else {
                                Log.d("Login_call", response.code() + "");
                                List<ApiError> error = ErrorUtils.parseError(response);
                                Log.d("Login_call_error", error.toString() + "");
                            }

                        }

                        @Override
                        public void onFailure(Call<UserResponse> call, Throwable t) {
                            Log.v(TAG, t.getMessage());


     }
});

最佳答案

您需要转换为 List<ApiError>因为那是你收到的:

Converter<ResponseBody, ApiError> converter = ApiClient.getClient()
            .responseBodyConverter(ApiError.class, new Annotation[0]);

转换为单个 ApiError .要转换为列表,您需要适当的转换器。这有点棘手,因为 type erasure

你需要一个Type您从 TypeToken 获得的像这样:

Type type = new TypeToken<List<ApiError>>() {}.getType();
Converter<ResponseBody, List<ApiError>> converter = ApiClient.getClient()
            .responseBodyConverter(type, new Annotation[0]);

还有几点

  • error.toString() ,因为 error现在是 List , 对你帮助不大。您可以使用 TextUtils.join("\n", error)相反。
  • return (List<ApiError>) new ApiError();没有意义。您不能像那样转换对象列表中的对象。最有可能的是,return new ArrayList<>();足以满足您的需求。

关于android - 使用改造 ResponseBody 的自定义消息错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39837998/

相关文章:

android - 使用 Horizo​​ntalListView 无法单击 HListView 中的项目

android - 按钮半屏宽

javascript - d3.js json结构添加数据

python - paho-mqtt 订阅一次性消息

java - 为什么Retrofit使用Interface而不是普通的java类?

Android 加速度计问题

java - 如何以静态和非静态方式使用枚举

php - 在 composer.json 中放入多个需求

java - 安卓改造失败()

retrofit - 正确使用 Retrofit + RxJava 的 combineLatest