2017-04-05 30 views
0

我正在使用返回json的服務器。其中一個要素是對象或虛假 - 它不是退出。我知道這是非常糟糕的服務器響應實現,並且有很多這樣的情況,但這是我必須處理的。我該如何處理這種情況?如果有一個對象我成功反序列化它,如果沒有 - 我得到錯誤 - 預期的對象找到BOOLEAN。 更糟糕的是,我不知道我將來會在這個項目中遇到這種情況。 這是樣品JSON:反序列化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": "" 
     } 
     ] 
    } 
    ] 
} 

正如你可以看到progress是假這裏。其他時候它是普通的對象,如depart。反序列化是通過Retrofit 2完成的。

非常感謝。

+0

你可以把你的代碼在這裏? –

+0

你只需要使用'GsonBuilder'創建一個自定義'Gson'實例'定製'polymorhic''TypeAdapter'或'JsonDeserializer',並將其添加到'GsonConverterFactory'實例即可。 –

+0

另一個最簡單的解決方案是在你的映射中將'progress'設置爲'java.lang.Object',讓Gson自己採取任何適當的反序列化策略。但是,這意味着您必須使用'instanceof'並在讀取該字段的位置鍵入強制轉換。 –

回答

1

我假設你有類似以下內容的頂層映射和配置了Retrofit實例Gson

final class Response { 

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

} 

final class Progress { 

    final String foo = null; 

} 

注意,progress屬性註解與詮釋@JsonAdapter:我們」再假設這是唯一的地方是在progress屬性可以是一個布爾值(如果你有很多地方像這樣的,您可以標註每個字段與此批註,或通過GsonBuilder.registerTypeAdapter();在.registerTypeAdapterFactory()情況下,出廠前必須覈對已知類型爲了不「攔截」所有類型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()。我刪除了第一個,然後把它放在try-catch中。似乎現在工作。 – Sermilion

+0

@Sermilion Aaah!不好意思,朋友!這完全是我的錯!我忘了清理它!給我一點時間。 –

+0

沒問題,讓我們刪除我們無用的評論)謝謝你。非常有用的答案,現在我完全理解它是如何工作的,並且能夠在其他情況下使用它。 – Sermilion