使用改造 ResponseBody 的自定义消息错误
custom message error using retrofit ResponseBody
我正在尝试使用 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.onResponse(MainActivity.java:77)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.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.onResponse(MainActivity.java:77)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.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;
}
}
ApiError:
public class ApiError {
@SerializedName("message")
private String message;
public ApiError() {
}
public String message() {
return message;
}
}
主要活动:
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
您需要从 TypeToken
获得的 Type
,如下所示:
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<>();
很可能足以满足您的需求。
我正在尝试使用 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.onResponse(MainActivity.java:77)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.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.onResponse(MainActivity.java:77)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.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;
}
}
ApiError:
public class ApiError {
@SerializedName("message")
private String message;
public ApiError() {
}
public String message() {
return message;
}
}
主要活动:
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
您需要从 TypeToken
获得的 Type
,如下所示:
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<>();
很可能足以满足您的需求。