在改造2中无法解析错误

在改造2中无法解析错误

本文介绍了在改造2中无法解析错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  RetrofitClient.APIError错误= RetrofitClient .ErrorUtils.parseError(response,retrofit); 

错误为空。更多详细信息:

这是API返回错误的格式:

 message:凭证不正确,
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();





$ b这是我的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 void void addHeadersRequiredForAllRequests(OkHttpClient httpClient,final String appVersion){
$ b $ class RequestInterceptor实现拦截器{

@Override
public com.squareup.okhttp.Response拦截(链式链接)抛出IOException {
请求请求= 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]);

API错误错误;

尝试{
error = converter.convert(response.errorBody());
} catch(IOException e){
e.printStackTrace();
返回新的APIError();
} catch(Exception e){
e.printStackTrace();
返回新的APIError();
}

返回错误;



public static class APIError {
@SerializedName(error)
public
ErrorResponse loginError;
$ b $ 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;

$ b @Override
public String toString(){
returnLoginErrorResponseBody {+
message ='+ getMessage()+' \''+
,statusCode =+ statusCode +
'}';
}

public void setMessage(String message){
this.message = message;
}
}
}


}

我得到了本教程中的错误utils类,但是稍微改变了它,因为它们的示例中的错误格式不同:



编辑:这是 Converter class:

  / ** 
*转换对象作为HTTP主体的对象。用
注册转换器*使用{@link Retrofit.Builder#addConverterFactory(Factory)}进行改造。
* /
public interface Converter< F,T> {
转换(F值)抛出IOException;

抽象类工厂{
/ **
*创建用于将HTTP响应主体转换为{@code type}的{@link Converter},或者如果它为$ b $,则为null b *不能由该工厂处理。
* /
公共转换器< ResponseBody,?> fromResponseBody(Type type,Annotation [] annotations){
return null;
}

/ **
*创建用于将{code类型}转换为HTTP请求主体的{@link Converter},如果
*不能为null由该工厂处理。
* /
公共转换器<?,RequestBody> toRequestBody(类型类型,注解[]注释){
返回null;




解决方案 您可以参考以下内容:



自定义类:

  public class ResponseError {

错误错误;

class错误{
int statusCode;
字符串消息;




$ b

将以下内容添加到 WebAPIService 界面:

  @GET(/ api / geterror)
调用< ResponseError> ; getError2();

然后,在 MainActivity.java中:

 调用< 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());
}

}
$ b @Override
public void onFailure(Throwable t){
Log.e(LOG_TAG,t.toString());
}
});






我刚刚测试过您的 RetrofitClient 类与我的Web服务。我给你的 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;
}

接口:

  public interface WebAPIService {
@GET(/ api / geterror)
调用< JSONObject> getError();
}

MainActivity:

 Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL_BASE)
.addConverterFactory(GsonConverterFactory.create() )
.build();

WebAPIService服务= retrofit.create(WebAPIService.class);

调用< JSONObject> jsonObjectCall = service.getError();
jsonObjectCall.enqueue(new Callback< JSONObject>(){
@Override $ b $ 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());
}

}
$ b @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 =凭证不正确,
statusCode = 401
};

var myError = new
{
error = detailError
};

返回Request.CreateResponse(HttpStatusCode.Unauthorized,myError);
}

工作正常!希望它有帮助!


I am using Retrofit 2 and I am getting a null pointer exception at this line:

 RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit);

The error is null. More details:

This is the format that the API returns the error in:

{
  "error": {
    "message": "Incorrect credentials",
    "statusCode": 401
  }
}

Here is my login Callback code:

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("");
        }
    }
}

This is my Retrofit 2 class:

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;
            }
        }
    }


}

I got the error utils class from this tutorial, but changed it slightly because the error formatting in their example is different:

EDIT: This is the Converter class:

/**
 * 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;
    }
  }
}
解决方案

UPDATE:

If you want to use a custom class instead of JSONObject below, you can refer to the following:

Custom class:

public class ResponseError {

    Error error;

    class Error {
        int statusCode;
        String message;
    }
}

Add the following to WebAPIService interface:

@GET("/api/geterror")
Call<ResponseError> getError2();

Then, inside 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());
    }
});


I have just tested your RetrofitClient class with my web service. I made a small update to your APIError class as the following (add 2 constructors, actually they are not called):

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();
}

MainActivity:

// 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());
    }
});

My web service (Asp.Net Web API):

According to your JSON response data, I have used the following code:

[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);
}

It's working! Hope it helps!

这篇关于在改造2中无法解析错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 07:51