Android 即使响应不是200,也要反序列化响应体

Android 即使响应不是200,也要反序列化响应体,android,retrofit2,Android,Retrofit2,我希望能够对同一Java对象的网络响应进行反序列化,即使响应未成功。当前,当我得到一个错误响应(如403)时,响应主体为null,我希望使用response.errorBody()方法读取已发送回的内容,这是正常的。然而,我想避免在改装回调中有很多代码仅仅用于反序列化errorBody。相反,我希望有一个拦截器,将errorBody的内容设置为body 原因是我有一个response对象,该对象包含错误和非错误响应的字段,并且根据响应的状态,一些字段预期为空,例如 错误响应JSON { "loc

我希望能够对同一Java对象的网络响应进行反序列化,即使响应未成功。当前,当我得到一个错误响应(如403)时,响应主体为null,我希望使用response.errorBody()方法读取已发送回的内容,这是正常的。然而,我想避免在改装回调中有很多代码仅仅用于反序列化errorBody。相反,我希望有一个拦截器,将errorBody的内容设置为body

原因是我有一个response对象,该对象包含错误和非错误响应的字段,并且根据响应的状态,一些字段预期为空,例如

错误响应JSON

{
"locked":true,
"remaining_attempts": 2
}
{
"name":"kev"
"token":"abcdefghijklmnopq"
}
成功响应JSON

{
"locked":true,
"remaining_attempts": 2
}
{
"name":"kev"
"token":"abcdefghijklmnopq"
}
我创建了一个Java对象来捕获两种场景:

class LoginResponse{
    @Expose
    private String name;
    @Expose
    private String token;
    @Expose
    private Boolean locked;
    @Expose
    private Integer remaining_attempts;
}

在拦截器中有这样做的方法吗?

您可以直接做如下响应

    LoginResponse errorResponse = gson.fromJson(response.errorBody().string(), LoginResponse.class);
…或使用拦截器

addInterceptor(getMyErrorResponseInterceptor())


protected Interceptor getMyErrorResponseInterceptor() {
    return new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Response response = chain.proceed(request);
            if (response.code() >= 400) {

                // handle error
            }

            return response;
        }
    };
}

改型是通过将序列化部分委托给转换器来完成的,您可以使用
builder.addConverterFactory(GsonConverterFactory.create())
而且已经有很多书面改装转换器,你可以找到它们中的大多数

因此,如果您想控制这个反序列化过程,您可以编写自定义转换器,如下所示

public class UnwrapConverterFactory extends Converter.Factory {

    private GsonConverterFactory factory;

    public UnwrapConverterFactory(GsonConverterFactory factory) {
        this.factory = factory;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(final Type type,
            Annotation[] annotations, Retrofit retrofit) {
        // e.g. WrappedResponse<Person>
        Type wrappedType = new ParameterizedType() {
            @Override
            public Type[] getActualTypeArguments() {
                // -> WrappedResponse<type>
                return new Type[] {type};
            }

            @Override
            public Type getOwnerType() {
                return null;
            }

            @Override
            public Type getRawType() {
                return WrappedResponse.class;
            }
        };
        Converter<ResponseBody, ?> gsonConverter = factory
                .responseBodyConverter(wrappedType, annotations, retrofit);
        return new WrappedResponseBodyConverter(gsonConverter);
    }
}
公共类UnwapConverterFactory扩展Converter.Factory{
私营GsonConverterFactory工厂;
公共换流器工厂(GsonConverterFactory工厂){
这个工厂=工厂;
}
@凌驾
公共转换器响应双转换器(最终类型,
注释[]注释,改装(改装){
//例如,包装响应
类型wrappedType=新参数化类型(){
@凌驾
公共类型[]getActualTypeArguments(){
//->包装响应
返回新类型[]{Type};
}
@凌驾
公共类型getOwnerType(){
返回null;
}
@凌驾
公共类型getRawType(){
返回WrappedResponse.class;
}
};
转换器gsonConverter=工厂
.responseBodyConverter(包装类型、注释、改装);
返回新的WrappedResponseBodyConverter(gsonConverter);
}
}
然后再次使用
addConverterFactory()
讲述新转换器的改装。 我应该提到的是,你可以使用多个转换器在改装这是可怕的,它只是检查转换器的顺序,直到找到一个合适的使用


参考资料:,

是的,我可以这样做,但我必须在所有翻新回调中这样做。我可以用拦截器来代替吗?是的,你可以用拦截器来捕捉所有的呼叫。你又能得到什么?这是一条400+以上的错误消息,有预期的正文吗?@kev已经更新为包含用于处理错误案例的拦截器。目前,我得到一个403,但我也想处理其他非200代码。在拦截器中,我被困在我现在想要用errorBody的内容填充响应正文的地方。我看到的是okhttp3.Response没有errorBody,在改型回调中,传递的是改型2。有错误体的响应我有类似的问题,搜索后我发现解决方案是编写一个自定义的
ConverterFactory
,扩展默认的改型转换器。@MohamedIbrahim有链接吗?我将在@kev上发布我的答案和更多信息