2017-04-05 19 views
0

jsonを返すサーバーを使用しています。要素の1つはオブジェクトか偽かのどちらかです - それは終了しません。私はこれがサーバーレスポンスの実装が非常に悪いことを知っていますが、そのようなケースはかなりありますが、これが私が処理しなければならないものです。どのようにこの状況に対処できますか?私は正常にそれを逆シリアル化するオブジェクトがある場合、何もない - 私はエラーが発生しました - オブジェクトが見つかりました。 さらに悪いことに、私はこのプロジェクトでこのような状況に将来どこで対処するのか分かりません。あなたはprogressがここに偽で見ることができるようにjsonがデシリアライズされているか、またはオブジェクトがRetrofitで処理されていますGsonConverterFactory

{ 
    "course": { 
    "id": "47902", 
    "course": "3844", 
    "group": "1825", 
    "teacher": "59502", 
    "table": "1447", 
    "client": "1", 
    "course_id": "3844", 
    "description": "" 
    }, 
    "teacher": { 
    "id": "59502", 
    "post": "0", 
    "experience": "", 
    "dep_experience": "", 
    "rank": "0", 
    "online": "1458891283", 
    "departments": [ 
     null 
    ] 
    }, 
    "depart": { 
    "id": "100", 
    "postcode": "", 
    "public": "1", 
    "alias": "", 
    "faculty": "97", 
    "client": "1" 
    }, 
    "progress": false, 
    "files": [ 
    { 
     "teacher": { 
     "id": "59502", 
     "code": "53bd7c21ad05b03e", 
     "photo": "1" 
     }, 
     "files": [ 
     { 
      "id": "0ffe41e5003ee5c0", 
      "owner": "59502", 
      "address": "0ffe41e5003ee5c0", 
      "type": "f", 
      "size": "0", 
      "time": "2015-07-10 14:39:15", 
      "data": "" 
     } 
     ] 
    } 
    ] 
} 

: これはサンプルJSONです。他の時はdepartのような普通のものです。逆シリアル化はRetrofit 2によって行われます。

ありがとうございます。 progressプロパティは@JsonAdapterアノテーションを付けていること

final class Response { 

    @SerializedName("progress") 
    @JsonAdapter(FalseAsNullTypeAdapterFactory.class) 
    final Progress progress = null; 

} 

final class Progress { 

    final String foo = null; 

} 

注:

+0

あなたのコードはここに置くことができますか? –

+0

'GsonBuilder'を使ってカスタムの' polymorhic '' TypeAdapter'や 'JsonDeserializer'を使ってカスタム' Gson'インスタンスを作成し、それを 'GsonConverterFactory'インスタンスに追加するだけで動作します。 –

+0

もう一つの最も簡単な解決策は、Gsonに適切なデシリアライズ戦略そのものを取らせるマッピングで '' java.lang.Object''を 'progress'にすることです。しかし、 'instanceof'を使用し、そのフィールドを読んだところで型キャストを使わなければならないということです。 –

答えて

1

私はあなたが次のようなトップレベルのマッピングを持っており、GsonのためにあなたのRetrofitインスタンスを設定したと仮定している私たちは」これが唯一の場所であると仮定すると、progressプロパティはブール値にすることができます(このような場所が多い場合は、このフィールドに注釈を付けるか、.registerTypeAdapter()からGsonBuilder経由); .registerTypeAdapterFactory()の場合は、すべてのtypを「傍受しない」ためにes)。

final class FalseAsNullTypeAdapterFactory 
     implements TypeAdapterFactory { 

    // Let Gson instantiate it itself 
    private FalseAsNullTypeAdapterFactory() { 
    } 

    @Override 
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) { 
     // Get a downstream parser (for simplicity: get the default parser for the given type) 
     final TypeAdapter<T> delegateTypeAdapter = gson.getDelegateAdapter(this, typeToken); 
     return new TypeAdapter<T>() { 
      @Override 
      public void write(final JsonWriter out, final T value) { 
       throw new UnsupportedOperationException(); 
      } 

      @Override 
      public T read(final JsonReader in) 
        throws IOException { 
       // Peek whether the next JSON token is a boolean 
       if (in.peek() == BOOLEAN) { 
        // And take the this JSON token as a boolean value 
        // Is it true? 
        if (in.nextBoolean()) { 
         // Then it's not something we can handle -- probably a boolean field annotated with @JsonAdapter(FalseAsNullTypeAdapterFactory.class)? 
         throw new MalformedJsonException("Unexpected boolean marker: true"); 
        } 
        // We're assuming it's null 
        return null; 
       } 
       // If it's not a boolean value, then we just delegate parsing to the original type adapter 
       return delegateTypeAdapter.read(in); 
      } 
     }; 
    } 

} 

今ちょうどそれをテストします:

今は、ここにあなたの問題に対処するタイプのアダプター工場で与えられたリソースがある

try (final Reader reader = getPackageResourceReader(Q43231983.class, "success.json")) { 
    final Response response = gson.fromJson(reader, Response.class); 
    System.out.println(response.progress.foo); 
} 
try (final Reader reader = getPackageResourceReader(Q43231983.class, "failure.json")) { 
    final Response response = gson.fromJson(reader, Response.class); 
    System.out.println(response.progress); 
} 

  • success.json{"progress":{"foo": "bar"}}です。
  • failure.jsonは、{"progress":false}である。

出力は次のとおりです。

バー
ヌル

+0

インポートが正しく行われました。だから、あなたは最終的なブール値b = in.nextBoolean()があることに気付きました。 in.nextBoolean()int try -catchです。私はまず最初に動作し、in.nextBoolean()にはどこにも行きません。私は最初のものを取り除き、試しにそのものを残しました。今働こうとしているようだ。 – Sermilion

+0

@Sermilion Aaah!ごめんなさい!それは完全に私の悪いです!私はそれをきれいにするのを忘れた!ちょっと待って。 –

+0

いいえ問題は、無駄なコメントを削除してください)ありがとうございました。非常に有用な答えと今私は完全にそれがどのように動作し、他の状況のた​​めにそれを使用することができる理解しています。 – Sermilion

関連する問題