- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 Retrofit 2,但在这一行出现空指针异常:
RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit);
错误为空。更多详情:
这是 API 返回错误的格式:
{
"error": {
"message": "Incorrect credentials",
"statusCode": 401
}
}
这是我的登录回调代码:
new Callback<LoginResponse>() {
@Override
public void onResponse(Response<LoginResponse> response, Retrofit retrofit) {
if (listener != null) {
if (response.isSuccess() && response.body() != null) {
User user = RetrofitUserToUserMapper.fromRetrofitUser(response.body().getLoginUser());
} else {
RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit);
listener.onUserLoginFailure(error.getErrorMessage()); // NPE - error is null
}
}
}
@Override
public void onFailure(Throwable t) {
if (listener != null) {
listener.onUserLoginFailure("");
}
}
}
这是我的 Retrofit 2 类:
public class RetrofitClient {
public static final String API_ROOT = "http://example.com/api/v1/";
private static final String HEADER_OS_VERSION = "X-OS-Type";
private static final String HEADER_APP_VERSION = "X-App-Version";
private static final String HEADER_OS_VERSION_VALUE_ANDROID = "android";
private RetrofitClient() {
}
private static Retrofit INSTANCE;
public static Retrofit getInstance() {
if (INSTANCE == null) {
setupRestClient();
}
return INSTANCE;
}
public static void setupRestClient() {
OkHttpClient httpClient = new OkHttpClient();
addHeadersRequiredForAllRequests(httpClient, BuildConfig.VERSION_NAME);
INSTANCE = new Retrofit.Builder()
.baseUrl(API_ROOT)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
}
private static void addHeadersRequiredForAllRequests(OkHttpClient httpClient, final String appVersion) {
class RequestInterceptor implements Interceptor {
@Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader(HEADER_OS_VERSION, HEADER_OS_VERSION_VALUE_ANDROID)
.addHeader(HEADER_APP_VERSION, appVersion)
.build();
return chain.proceed(request);
}
}
httpClient.networkInterceptors().add(new RequestInterceptor());
}
public static class ErrorUtils {
public static APIError parseError(Response<?> response, Retrofit retrofit) {
Converter<ResponseBody, APIError> converter =
retrofit.responseConverter(APIError.class, new Annotation[0]);
APIError error;
try {
error = converter.convert(response.errorBody());
} catch (IOException e) {
e.printStackTrace();
return new APIError();
} catch (Exception e) {
e.printStackTrace();
return new APIError();
}
return error;
}
}
public static class APIError {
@SerializedName("error")
public
ErrorResponse loginError;
public ErrorResponse getLoginError() {
return loginError;
}
public String getErrorMessage() {
return loginError.message;
}
private class ErrorResponse {
@SerializedName("message")
private String message;
@SerializedName("statusCode")
public int statusCode;
public String getMessage() {
return message;
}
public int getStatusCode() {
return statusCode;
}
@Override
public String toString() {
return "LoginErrorResponseBody{" +
"message='" + getMessage() + '\'' +
", statusCode=" + statusCode +
'}';
}
public void setMessage(String message) {
this.message = message;
}
}
}
}
我从本教程中得到了错误 utils 类,但由于他们示例中的错误格式不同而对其进行了轻微更改:
编辑:这是 Converter
类:
/**
* Convert objects to and from their representation as HTTP bodies. Register a converter with
* Retrofit using {@link Retrofit.Builder#addConverterFactory(Factory)}.
*/
public interface Converter<F, T> {
T convert(F value) throws IOException;
abstract class Factory {
/**
* Create a {@link Converter} for converting an HTTP response body to {@code type} or null if it
* cannot be handled by this factory.
*/
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
return null;
}
/**
* Create a {@link Converter} for converting {@code type} to an HTTP request body or null if it
* cannot be handled by this factory.
*/
public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) {
return null;
}
}
}
最佳答案
更新:
如果你想使用自定义类而不是下面的JSONObject
,你可以引用以下内容:
自定义类:
public class ResponseError {
Error error;
class Error {
int statusCode;
String message;
}
}
在WebAPIService
接口(interface)中添加如下内容:
@GET("/api/geterror")
Call<ResponseError> getError2();
然后,在 MainActivity.java
中:
Call<ResponseError> responseErrorCall = service.getError2();
responseErrorCall.enqueue(new Callback<ResponseError>() {
@Override
public void onResponse(Response<ResponseError> response, Retrofit retrofit) {
if (response.isSuccess() && response.body() != null){
Log.i(LOG_TAG, response.body().toString());
} else {
if (response.errorBody() != null){
RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit);
Log.e(LOG_TAG, error.getErrorMessage());
}
}
}
@Override
public void onFailure(Throwable t) {
Log.e(LOG_TAG, t.toString());
}
});
我刚刚用我的 Web 服务测试了您的 RetrofitClient
类。我对您的 APIError
类做了如下小更新(添加 2 个构造函数,实际上它们没有被调用):
public APIError(){
this.loginError = new ErrorResponse();
}
public APIError(int statusCode, String message) {
this.loginError = new ErrorResponse();
this.loginError.statusCode = statusCode;
this.loginError.message = message;
}
接口(interface):
public interface WebAPIService {
@GET("/api/geterror")
Call<JSONObject> getError();
}
主要 Activity :
// Retrofit 2.0-beta2
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL_BASE)
.addConverterFactory(GsonConverterFactory.create())
.build();
WebAPIService service = retrofit.create(WebAPIService.class);
Call<JSONObject> jsonObjectCall = service.getError();
jsonObjectCall.enqueue(new Callback<JSONObject>() {
@Override
public void onResponse(Response<JSONObject> response, Retrofit retrofit) {
if (response.isSuccess() && response.body() != null){
Log.i(LOG_TAG, response.body().toString());
} else {
if (response.errorBody() != null){
RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit);
Log.e(LOG_TAG, error.getErrorMessage());
}
}
}
@Override
public void onFailure(Throwable t) {
Log.e(LOG_TAG, t.toString());
}
});
我的网络服务(Asp.Net Web API):
根据你的JSON响应数据,我使用了如下代码:
[Route("api/geterror")]
public HttpResponseMessage GetError()
{
var detailError = new
{
message = "Incorrect credentials",
statusCode = 401
};
var myError = new
{
error = detailError
};
return Request.CreateResponse(HttpStatusCode.Unauthorized, myError);
}
它的工作!希望对您有所帮助!
关于android - 无法解析 Retrofit 2 中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34462019/
我正在尝试迁移我的应用程序以使用 RxJava。我已经在使用 Retrofit,因此我正在尝试使用方法返回 Observables 的 Retrofit 接口(interface)。但是我现在在针对它
我想 post 数据如下: { "user_id":"14545646", "list":["4545645","4545645","4545645","4545645"]
我是改造新手。我向网站发出 POST 请求。网站以 HTML 形式返回响应。所以我会解析它。但是 Retrofit 尝试将其解析为 JSON。怎么办? @FormUrlEncoded @POST("/
我想异步执行 2 个网络调用 - 我正在使用 Retrofit+RxJava 来完成这个。这个逻辑来自一个简单的 Runner 类来测试解决方案。注意:这主要涉及服务器端的 RxJava。 我的代码如
我最近在改造的存储库中使用 Flow。 Result 的密封类 enum class ApiStatus{ SUCCESS, ERROR, LOADING } sealed c
我目前正在开发 Retrofit2 客户端的错误处理部分(使用 Retrofit 的 Rx 实现)。 找了一段时间,没有找到简单的方法将Retrofit返回的ResponseBody反序列化到我报错的
我从 retrofit 更新到 retrofit2 后出现此错误。 FATAL EXCEPTION: OkHttp Dispatcher Process: nz.co.datacom.mars.jun
在使用 RxJava 和 Retrofit 2 时,我正在尝试创建单元测试来覆盖我的应用何时收到特定响应。 我遇到的问题是,在 Retrofit 2 中,我看不到在不使用反射的情况下创建 retrof
在 Retrofit 1.9.x 中有一个 RetrofitError.Kind.NETWORK这让您可以轻松确定故障是否由网络错误引起。在新的 2.0 API 中,我们不再有 RetrofitErr
有没有办法用Refit动态输入参数? 我的 Refit 界面中有这段代码: [Get("/click?{parm}")] Task> SaveClick(string parm
有没有办法用Refit动态输入参数? 我的 Refit 界面中有这段代码: [Get("/click?{parm}")] Task> SaveClick(string parm
我知道,Retrofit 在内部使用 OkHttp。但是,我可以看到一些开发人员提供了以下方法的应用 return new Retrofit.Builder() .baseUrl(Bu
在项目上安装这个库之后: compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'io.reactivex.rxjava2:rxjava:2.0
在 Retrofit 1.x 中,我使用以下模式创建 API 服务类,该类模拟某些构建变体的不良网络连接。 // Retrofit 1 private T create(Class apiServi
Retrofit请求API格式(Android): @POST("getOrderStatus") @Headers("Content-Type:application/json") Obser
当我实例化 RestAdapter 时,我的应用程序总是崩溃 private void submitForm(SignupForm form){ RestAdapter adapter = n
我正要从 retrofit 1.9 迁移到最新版本并遇到问题... 我的设置: 三星 Galaxy S7 Edge(Android 7) 改造 2.3 OkHttp 3.8 迁移后突然遇到这个问题:
我正在尝试在 2.5.1-SNAPSHOT 中使用 retrofit 的协程支持,但我不断收到一个奇怪的异常。 我的改造服务类有: @GET("weather") suspend fun getFor
我正在尝试 Ktor通过转换一些当前正在使用的现有项目 Retrofit . 虽然我可以很容易地将请求转换为: client.get { url("$BASE_URL/something/so
使用改造 2,如何为上传的文件设置动态名称? 目前是这样的: @Part("avatar\"; filename=\"image\" ") RequestBody image, 但是,上传的文件名将是
我是一名优秀的程序员,十分优秀!