2017-02-12 6 views
1

GSONとRxJavaで改造を使用してネットワーク要求を実行しています。私は、Gsonライブラリがそれを変換することができないときに応答を得る方法を理解しようとしています。ハンドルの改造2 GSON変換エラー

これは、サーバーでエラーが発生し、応答がGsonライブラリが応答を変換しようとしているクラスと一致しない場合に発生します。

インターセプタを作成し、変換しようとする前にレスポンスをキャッシュするのが回避策です。しかし、これは単なる悪いプログラミングであり、同時リクエストを開始すると問題が管理不能になるためです。

サービスは次のように定義されています。レスポンスクラスには、ステータスコードとdataというジェネリックタイプのみが含まれています。

Retrofit getService() { 
    return new Retrofit.Builder() 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .baseUrl(url) 
      .client(clientBuilder.build()) 
      .build(); 
} 
public Observable<Response<String>> userLogin(String username, String password) { 

    return getService().create(Account.class) 
      .login(username, password) 
      .subscribeOn(Schedulers.newThread()) 
      .observeOn(AndroidSchedulers.mainThread()); 
} 

サーバは、文字列以外の何かを返す場合、他の我々は要求を作成するコード

getService().userLogin(email, password) 
     .subscribeOn(Schedulers.newThread()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(onSuccess(), onError()); 

protected Action1<Response<String>> onSuccess(){ 

    return new Action1<Response<String>>() { 
     @Override 
     public void call(Response<String> response) { 
      // Process the response 
     } 
    }; 
} 
protected Action1<Throwable> onError(){ 
    return new Action1<Throwable>() { 
     @Override 
     public void call(Throwable throwable) { 

      if (throwable instanceof HttpException) { 
       ResponseBody body = ((HttpException) throwable).response().errorBody(); 
       // Handle the error 
      } 
     } 
    }; 

のどこかに問題が発生します。オブジェクトや配列などです。ここで、GsonConverterFactoryは、onErrorメソッドによってキャッチされるエラーをスローします。私はどのように応答を得ることができますかと思います。

戻されるスロー可能オブジェクトはJsonSyntaxExceptionです。悲しいことに、GSONライブラリが変換しようとした元の応答本体は含まれていません。

答えて

0

昨日私はsimilar solutionに同様の質問を提案しましたが、答えを少し変更する必要があるようです。答えには、効率とメモリ消費の懸念に関するコメントも含まれています。それが唯一のinstanceof EDになる可能性があり、特別なプライベート・コンストラクタ例外がスローされますログインするよりも、むしろ

final class BadPayloadExceptionConversionThrowableConsumer 
     implements IConversionThrowableConsumer { 

    private static final int MAX_STREAM_BUFFER_LENGTH = 8 * 1024; 

    private static final IConversionThrowableConsumer badPayloadExceptionConversionThrowableConsumer = new BadPayloadExceptionConversionThrowableConsumer(); 

    private BadPayloadExceptionConversionThrowableConsumer() { 
    } 

    static IConversionThrowableConsumer getBadPayloadExceptionConversionThrowableConsumer() { 
     return badPayloadExceptionConversionThrowableConsumer; 
    } 

    @Override 
    public void accept(final MediaType contentType, final long contentLength, final InputStream inputStream, final Throwable ex) 
      throws IOException { 
     final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(MAX_STREAM_BUFFER_LENGTH); 
     copy(limit(inputStream, MAX_STREAM_BUFFER_LENGTH), byteArrayOutputStream); 
     final ByteArrayInputStream bufferedInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); 
     throw new BadPayloadException(ex, contentType, contentLength, bufferedInputStream); 
    } 

    static final class BadPayloadException 
      extends IOException { 

     private final MediaType contentType; 
     private final long contentLength; 
     private final InputStream inputStream; 

     private BadPayloadException(final Throwable cause, final MediaType contentType, final long contentLength, final InputStream inputStream) { 
      super(null, cause); 
      this.contentType = contentType; 
      this.contentLength = contentLength; 
      this.inputStream = inputStream; 
     } 

     MediaType getContentType() { 
      return contentType; 
     } 

     long getContentLength() { 
      return contentLength; 
     } 

     InputStream getInputStream() { 
      return inputStream; 
     } 

    } 

} 

:あなたはそのソリューションを使用したい場合は、いくつかの障害情報を保持する特別な例外を作成することができ、特別なエラーハンドラを作成することができますコールサイトで。入力ストリームは、関連する質問(特にInputStreamのrawが委任されているが、なぜならResponseBodyではない理由)にコメントされている理由で、ある制限までバッファリングする必要があります。今では使用することができます方法:

service.getFooBar() 
     .subscribe(
       out::println, 
       t -> { 
        if (t instanceof BadPayloadException) { 
         try { 
          final BadPayloadException badPayloadException = (BadPayloadException) t; 
          err.println("Content type = " + badPayloadException.getContentType()); 
          err.println("Content length = " + badPayloadException.getContentLength()); 
          err.print("Content  = "); 
          copy(badPayloadException.getInputStream(), err); 
         } catch (final IOException ex) { 
          throw new RuntimeException(ex); 
         } 
        } else { 
         err.println(t.getClass()); 
        } 
       } 
     ); 

copylimit方法はGoogleのグアバByteStreamsから静的な輸入品であることを。 outおよびerrは、それぞれSystem.outおよびSystem.errの静的インポートです。

出力例:

Content type = application/json 
Content length = -1 
Content  = {#"foo":1,"bar":2} 
関連する問題