2017-07-04 64 views
3

即使响应不成功,我也希望能够对同一个Java对象的网络响应进行反序列化。目前,当我收到类似403的错误响应时,响应正文为空,我期望使用response.errorBody()方法读取已发回的内容,这是正确的。不过,我想避免在改进回调中使用大量代码,只是为了反序列化errorBody。相反,我想有一个拦截器,将errorBody的内容设置为body。Retrofit2即使响应不是200反序列化响应主体

这样做的原因是,我有了两个错误和非错误响应领域,并根据某些领域,预计该响应的状态响应对象,以保留为空如

错误响应JSON

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

成功响应JSON

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

我已经创建了捕获这两种情况下一个Java对象:

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

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

+0

我有类似的问题,搜索后我发现,解决办法是编写一个自定义'ConverterFactory'扩展默认改造转换。 –

+0

@MohamedIbrahim任何链接? – kev

+0

我会发布我的答案和更多信息@kev –

回答

0

你可以这样做直接响应以下...

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

是的,我可以这样做,但我必须在所有改进回调中都这样做。我可以在拦截器中做到吗? – kev

+0

是的,你可以有一个拦截器来捕捉所有的电话。你回来的是什么?它是一个400+的错误消息,与预期的身体? – TooManyEduardos

+0

@kev已更新为包含拦截器以处理错误案例 –

1

改造是由它委托给转换器做连载,你你可以通过使用builder.addConverterFactory(GsonConverterFactory.create()) 添加一个特定的建设者,并且已经有很多书面的Retrofit转换器,你可以找到它们中的大多数here

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

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中使用多个转换器,这非常棒,它只需按顺序检查转换器,直到找到合适的转换器。

资源:writing custom Retrofit converterusing multiple converters