2016-04-21 5 views
6

とJSONアレイデシリアライズ:いくつかのフィールドに基づいGsonは私は次のようにいくつかの奇妙なJSONを有する複数のオブジェクトタイプ

[ 
    { 
    "type":"0", 
    "value":"my string" 
    }, 
    { 
    "type":"1", 
    "value":42 
    }, 
    { 
    "type":"2", 
    "value": { 
    } 
    } 
] 

を、アレイ内のオブジェクトは、特定のタイプです。 Gsonを使用して、私はTypeAdapterにこれらの特定の型のデリゲートアダプタを送信するTypeAdapterFactoryを持つことを考えていますが、作成する型を知るための "type"フィールドを読む良い方法を理解していません。 TypeAdapterで 、

Object read(JsonReader in) throws IOException { 
    String type = in.nextString(); 
    switch (type) { 
    // delegate to creating certain types. 
    } 
} 

は、 "タイプ" フィールドには、私のJSONに最初に来ると仮定します。その前提を取り除くうまい方法がありますか?

答えて

8

ここに、JsonのNewsFeedArticleとNewsFeedAdアイテムの配列を処理するために書いたコードがあります。どちらのアイテムも、マーカーインターフェイスのNewsFeedItemを実装して、特定のフィールドにTypeAdaterを使用するかどうかを簡単に確認できます。

public class NewsFeedItemTypeAdapterFactory implements TypeAdapterFactory { 

    @Override 
    @SuppressWarnings("unchecked") 
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { 
     if (!NewsFeedItem.class.isAssignableFrom(type.getRawType())) { 
      return null; 
     } 

     TypeAdapter<JsonElement> jsonElementAdapter = gson.getAdapter(JsonElement.class); 
     TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedArticle.class)); 
     TypeAdapter<NewsFeedAd> newsFeedAdAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedAd.class)); 

     return (TypeAdapter<T>) new NewsFeedItemTypeAdapter(jsonElementAdapter, newsFeedArticleAdapter, newsFeedAdAdapter).nullSafe(); 
    } 

    private static class NewsFeedItemTypeAdapter extends TypeAdapter<NewsFeedItem> { 

     private final TypeAdapter<JsonElement> jsonElementAdapter; 
     private final TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter; 
     private final TypeAdapter<NewsFeedAd> newsFeedAdAdapter; 

     NewsFeedItemTypeAdapter(TypeAdapter<JsonElement> jsonElementAdapter, 
       TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter, 
       TypeAdapter<NewsFeedAd> newsFeedAdAdapter) { 
      this.jsonElementAdapter = jsonElementAdapter; 
      this.newsFeedArticleAdapter = newsFeedArticleAdapter; 
      this.newsFeedAdAdapter = newsFeedAdAdapter; 
     } 

     @Override 
     public void write(JsonWriter out, NewsFeedItem value) throws IOException { 
      if (value.getClass().isAssignableFrom(NewsFeedArticle.class)) { 
       newsFeedArticleAdapter.write(out, (NewsFeedArticle) value); 

      } else if (value.getClass().isAssignableFrom(NewsFeedAd.class)) { 
       newsFeedAdAdapter.write(out, (NewsFeedAd) value); 

      } 

     } 

     @Override 
     public NewsFeedItem read(JsonReader in) throws IOException { 
      JsonObject objectJson = jsonElementAdapter.read(in).getAsJsonObject(); 

      if (objectJson.has("Title")) { 
       return newsFeedArticleAdapter.fromJsonTree(objectJson); 

      } else if (objectJson.has("CampaignName")) { 
       return newsFeedAdAdapter.fromJsonTree(objectJson); 
      } 

      return null; 
     } 
    } 
} 

これをGsonに登録するには、次のコードを使用します。

return new GsonBuilder() 
     .registerTypeAdapterFactory(new NewsFeedItemTypeAdapterFactory()) 
     .create(); 
+0

コードを改善してくれたJakeに感謝します。 –

+1

うん、良い例、あまりにも! –

関連する問題