2017-07-04 13 views
3

レスポンスが成功しなくても、同じJavaオブジェクトに対するネットワークレスポンスをデシリアライズできます。現在403のようなエラーレスポンスが返ってくると、レスポンスボディはnullになり、返されたものを読むためにresponse.errorBody()メソッドを使用することが期待されます。これは問題ありません。しかし、私はerrorBodyを直列化解除するために、改造コールバックに多くのコードを書くことを避けたい。代わりに、errorBodyの内容を本文に設定するインターセプタを用意したいと思います。Retrofit2レスポンスが200でない場合でもレスポンス本体をデシリアライズする

この理由は、私はエラーと非エラー応答の両方のフィールドを持っていると応答の状況に応じて、いくつかのフィールドがヌル例えば

エラーレスポンスJSONを残されることが期待されるレスポンスオブジェクトを持っているということです

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

成功レスポンス、私は両方のシナリオをキャプチャする単一のJavaオブジェクトを作成した

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

JSON:

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()) を使用してビルダーに特定のものを追加することができます。すでに多くのレトロフィットコンバータが作成されていますが、そのほとんどはhereです。

ので、あなたは、逆シリアル化のこのプロセスを制御したい場合、あなたは、あなたが新しいコンバータについて改修を伝えるために再びaddConverterFactory()を使用して、この

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

のようなあなたのカスタムコンバータ、何かを書くことができます。 Retrofitで複数のコンバーターを使用することができますが、使用する適切なコンバータが見つかるまで順番にコンバーターをチェックするだけです。

資源:writing custom Retrofit converterusing multiple converters

関連する問題