Retrofit2 反序列化响应体,即使响应不是 200 [英] Retrofit2 Deserialize response body even if response is not 200

查看:104
本文介绍了Retrofit2 反序列化响应体,即使响应不是 200的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使响应不成功,我也希望能够反序列化对同一个 Java 对象的网络响应.目前,当我收到类似 403 的错误响应时,响应正文为空,我希望使用 response.errorBody() 方法来读取已发回的任何内容,这没关系.但是我想避免在改造回调中包含大量代码只是为了反序列化 errorBody.相反,我想要一个拦截器,将 errorBody 的内容设置为 body.

I want to be able to deserialize network response to the same Java object even if response is not succesfull. Currently when I get an error response like 403, the response body is null, and I'm expected to use the response.errorBody() method to read whatever has been sent back, which is ok. However I want to avoid having alot of code in the retrofit callbacks just for deserializing errorBody. Instead I want to have an interceptor that sets the content of errorBody into body.

这样做的原因是我有一个响应对象,其中包含错误和非错误响应的字段,并且根据响应的状态,某些字段预计将保留为空,例如

The reason for this is that I have a response object that has fields for both error and non error responses and depending on the status of the response some fields are expected to be left null e.g

错误响应 JSON

{
"locked":true,
"remaining_attempts": 2
}

成功响应 JSON

{
"name":"kev"
"token":"abcdefghijklmnopq"
}

我创建了一个捕获这两种场景的 Java 对象:

I have created a single Java object that captures both scenarios:

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

有没有办法在拦截器中做到这一点?

Is there way to do this in an interceptor?

推荐答案

Retrofit 通过将序列化部分委托给 Converter 来完成序列化部分,您可以使用 builder.addConverterFactory(GsonConverterFactory(GsonConverterFactory).create())并且已经有很多书面的 Retrofit 转换器,您可以在 here.

Retrofit is doing the serialization part by delegating it to the Converter, you you can add a specific one to the builder by using builder.addConverterFactory(GsonConverterFactory.create()) and there is already many written Retrofit Converters, you can find most of them here.

所以如果你想控制这个反序列化的过程,你可以编写你的自定义转换器,像这样

so if you want to control this process of deserialization, you can write your custom converter, something like this

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

然后你再次使用 addConverterFactory() 告诉 Retrofit 新的转换器.我应该提到,你可以在 Retrofit 中使用多个转换器,这很棒,它只是按顺序检查转换器,直到找到合适的使用.

then you use addConverterFactory() again to tell Retrofit about the new converter. I should mention that you can use multiple converters in Retrofit which is awesome, it simply check converters by order till find the proper one to use.

资源:编写自定义改造转换器, 使用多个转换器

这篇关于Retrofit2 反序列化响应体,即使响应不是 200的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆