2015-10-15 39 views
0

我有一個與多個JSON響應一起工作的模型。然而這樣的迴應:在GSON上使用JsonDeserializer

items: [ 
{ 
kind: "youtube#playlistItem", 
etag: ""fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/jqbcTLu8tYm8b1FXGO14gNZrFG4"", 
id: "PLUQ7I1jJqKB4lJarGcpWsP62l7iC06IkE2LDE0BxLe18", 

與此一個衝突(注意不同類型相同id場以上idString,另一種是Class):

items: [ 
{ 
kind: "youtube#searchResult", 
etag: ""fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/hDIU49vmD5aPhKUN5Yz9gtljG9A"", 
id: { 
kind: "youtube#playlist", 
playlistId: "PLh6xqIvLQJSf3ynKVEc1axUb1dQwvGWfO" 
}, 

我想使用單個模型類閱讀id字段。

這是我的模型Response類:

public class Response { 
    private ArrayList<Item> items = new ArrayList<Item>(); 

這是我的模型Item類:

public class Item { 
    private Id id; 

//nested class inside Item 
public class Id 
{ 
    private String id; 
    private String kind; 
    private String playlistId; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getKind() { 
     return kind; 
    } 

    public void setKind(String kind) { 
     this.kind = kind; 
    } 

    public String getPlaylistId() { 
     return playlistId; 
    } 

    public void setPlaylistId(String playlistId) { 
     this.playlistId = playlistId; 
    } 
} 

注意,Id類是內部Item類。

這是我如何使用registerTypeAdapter

GsonBuilder gsonBuilder = new GsonBuilder(); 
      gsonBuilder.registerTypeAdapter(Response.class, 
        new JsonDeserializer<Item.Id>() { 
         @Override 
         public Item.Id deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { 
          Item.Id result = new Item().new Id(); 

          if(jsonElement.isJsonPrimitive() == false) 
          { 
           result.setKind(jsonElement.getAsJsonObject().get("kind").getAsString()); 
           result.setPlaylistId(jsonElement.getAsJsonObject().get("playlistId").getAsString()); 
           //return new Item.Id(jsonElement.getAsJsonObject().get("kind").getAsString(), jsonElement.getAsJsonObject().get("playlistId").getAsString()); 
           return result; 
          } 
          else 
          { 
           result.setId(jsonElement.getAsString()); 
           //return new Item.Id(jsonElement.getAsString()); 
           return result; 
          } 
         } 
        }); 
      Gson gson = gsonBuilder.create(); 

      Response result = Response.success(
        gson.fromJson(json, gsonClass), 
        HttpHeaderParser.parseCacheHeaders(response)); 

但是上面的代碼拋出這一行java.lang.NullPointerException

if(jsonElement.isJsonPrimitive() == false) 

我應該怎麼辦? 這是使用registerTypeAdapter的正確方法嗎?

感謝您的時間

+0

你傳遞的json的價值是什麼?那麼Response.class是如何定義的? –

回答

1

你的主要問題似乎是,你在註冊類型適配器Response類,但你給一個JsonDeserializer,處理Item.Id類。要麼你反序列化全Response或限制自己Item甚至Item.Id

與反序列化Item.Id(寫在你的問題)的另一個問題是直接說這是一個 - 靜態內部類,它需要實例化父類的實例(與使用new Item().new Id()時一樣)。我認爲如果你想保留它,你將不得不手動反序列化整個Item,坦率地說,我沒有看到任何理由不讓Item.Id成爲靜態的,因爲它會簡化問題。

這裏是我與靜態版本的Item.Id

GsonBuilder builder = new GsonBuilder(); 
builder.registerTypeAdapter(Item.Id.class, new JsonDeserializer<Item.Id>() { 
    @Override 
    public Item.Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     Item.Id id = new Item.Id(); 
     if (!json.isJsonPrimitive()) { 
      JsonObject jsonObject = json.getAsJsonObject(); 
      id.setKind(jsonObject.get("kind").getAsString()); 
      id.setPlaylistId(jsonObject.get("playlistId").getAsString()); 
     } else { 
      id.setId(json.getAsString()); 
     } 
     return id; 
    } 
}); 

及一些測試片段,似乎爲我工作的解決方案:

Gson gson = builder.create(); 
Response response = gson.fromJson("{\n" + 
     " \"items\": [\n" + 
     "  {\n" + 
     "   \"kind\": \"youtube#playlistItem\",\n" + 
     "   \"etag\": \"fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/jqbcTLu8tYm8b1FXGO14gNZrFG4\",\n" + 
     "   \"id\": \"PLUQ7I1jJqKB4lJarGcpWsP62l7iC06IkE2LDE0BxLe18\"\n" + 
     "  }\n" + 
     " ]\n" + 
     "}", Response.class); 

Response response2 = gson.fromJson("{\n" + 
     " \"items\": [\n" + 
     "  {\n" + 
     "   \"kind\": \"youtube#searchResult\",\n" + 
     "   \"etag\": \"fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/hDIU49vmD5aPhKUN5Yz9gtljG9A\",\n" + 
     "   \"id\": {\n" + 
     "    \"kind\": \"youtube#playlist\",\n" + 
     "    \"playlistId\": \"PLh6xqIvLQJSf3ynKVEc1axUb1dQwvGWfO\"\n" + 
     "   }\n" + 
     "  }\n" + 
     " ]\n" + 
     "}", Response.class); 

如果你想保持Item.Id非靜態,我想您需要爲Item編寫解串器。另外請記住,json元素可以不存在,但解析器應該仍然能夠處理它。

+0

非常感謝你的努力來寫這個答案。它太糟糕了,我只能讚揚一次。希望別人能夠讚揚這個偉大的答案。再次感謝:) –

+0

如果我可以添加一個問題,爲什麼我需要反序列化整個'項目',如果我不讓內部'ID'類靜態? –

+1

@BlazeTama實際上,我不是100%確定的,但是非靜態內部類的實例有一個對其父類的引用,所以我會想象你需要該引用來創建它的一個實例。 ..我不知道是否有一些Java下的魔術,當你將它分配給另一個父實例(我認爲不是)時,它會改變對另一個父類實例的引用。如果它像我認爲的那樣工作,那麼您最終會在內部引用某個其他Item實例。 – Zharf

1

我剛剛同樣的問題很久以前的事,但我用Json.Net工作的話,但是JSON的概念是(幾乎)一樣的,所以我希望我會成功的幫助。 我想這可能不起作用,但爲什麼不嘗試註冊Item類?我的意思是沒有'Item.Id',所以它是有意識的得到一個null。但這:gsonBuilder.registerTypeAdapter(Item.class,可能會失敗,因爲你不明確解析Item類(但它可能工作,我只是從未在Gson中嘗試過,但在Json.Net中類似的方式將正常工作。) 那麼,你怎麼能解決這個問題?我懶得寫一個paraser但你可以看看here和讀取here(搜索的蘇爾特摘要摘要Using the registerTypeAdapter()。 我希望我幫助。