2013-06-07 5 views
6

私はJSONArrayをGsonでデシリアライズしようとしていますが、値の型は異なる場合があります。値 "in_wanted"はbooleanまたはJSONObjectです。Gsonはさまざまな値タイプのjsonを逆シリアル化します

JSONObjectとしてin_wanted
{ 
"movies": [ 
     { 
      "title": "example boolean", 
      "in_wanted": false 
     } 
    ]   
} 

{ 
"movies": [ 
     { 
      "title": "example object", 
      "in_wanted": { 
       "profile": { 
        "value": false 
       } 
      } 
     } 
    ]   
} 

それが利用可能だ時はいつでも、私は、オブジェクトを必要とし、 "in_wanted" の値がある時はいつでも私がnullを返すようにデシリアライザが必要booleanとしてin_wanted

ブール値。 Gsonでこれを行う最善の方法は何でしょうか?

+0

をその後、単純Gsonデシリアライザの仕事をできるようにしようと、それはヌルとしての基準をさせてください。 – Pragmateek

答えて

10

あなたはこれを行うことができますカスタムデシリアライザを使用します。最初にJSONを表すデータモデルを作成する必要があります。我々は、すべての必要なクラスを持っているとき

class JsonEntity { 

    private List<Movie> movies; 

    public List<Movie> getMovies() { 
     return movies; 
    } 

    public void setMovies(List<Movie> movies) { 
     this.movies = movies; 
    } 

    @Override 
    public String toString() { 
     return "JsonEntity [movies=" + movies + "]"; 
    } 
} 

class Movie { 

    private String title; 
    private Profile in_wanted; 

    public String getTitle() { 
     return title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 

    public Profile getIn_wanted() { 
     return in_wanted; 
    } 

    public void setIn_wanted(Profile in_wanted) { 
     this.in_wanted = in_wanted; 
    } 

    @Override 
    public String toString() { 
     return "Movie [title=" + title + ", in_wanted=" + in_wanted + "]"; 
    } 
} 

class Profile { 

    private boolean value; 

    public boolean isValue() { 
     return value; 
    } 

    public void setValue(boolean value) { 
     this.value = value; 
    } 

    @Override 
    public String toString() { 
     return String.valueOf(value); 
    } 
} 

今、私たちは、新しいカスタムデシリアライザを実装する必要があります。JsonProfileクラスの表情を持っている

class ProfileJsonDeserializer implements JsonDeserializer<Profile> { 
    @Override 
    public Profile deserialize(JsonElement jsonElement, Type type, 
      JsonDeserializationContext context) throws JsonParseException { 
     if (jsonElement.isJsonPrimitive()) { 
      return null; 
     } 

     return context.deserialize(jsonElement, JsonProfile.class); 
    } 
} 

class JsonProfile extends Profile { 

} 

してください。 「デシリアライゼーションループ」(トリッキーな部分)を避けるために作成する必要があります。

そして今、我々は、試験方法に当社のソリューションをテストすることができます:あなたがクラスにマッピングしている場合

GsonBuilder builder = new GsonBuilder(); 
builder.registerTypeAdapter(Profile.class, new ProfileJsonDeserializer()); 
Gson gson = builder.create(); 

JsonEntity jsonEntity = gson.fromJson(new FileReader("/tmp/json.txt"), 
     JsonEntity.class); 
System.out.println(jsonEntity); 
+2

@Meatje:これは私のコメントで話した別の可能性です... – MikO

+0

@MikOの疑いがあるので、手動解析は大きな仕事でしたので、これはトリックでした。両方とも助けてくれてありがとう! – Meatje

3

あなたは手動解析を行うことができ、何かのように:

JsonParser parser = new JsonParser(); 
JsonObject rootObject = parser.parse(yourJsonString).getAsJsonObject(); 
JsonObject movieObject = rootObject 
          .getAsJsonArray("movies") 
          .get(0).getAsJsonObject(); 
JsonElement inWantedElement = movieObject.get("in_wanted"); 

//Check if "in_wanted" element is a boolean or an object 
if (inWantedElement.isJsonObject()) { 
    //Process the element as an object... 
    //for example get the element "value"... 
    boolean value = inWantedElement 
         .getAsJsonObject() 
         .getAsJsonObject("profile") 
         .getAsJsonPrimitive("value") 
         .getAsBoolean(); 
} 
else if (inWantedElement.isJsonPrimitive()) { 
    //Process the element as a boolean... 
    boolean inWanted = inWantedElement.getAsBoolean(); 
} 

注:タイプJsonObjectJsonArrayJsonElementについての更なる情報についてはGson API documentationを参照してください、というように...

+0

これはin_wanted値に対してのみ可能ですか?だから、私は、配列の他の値(デフォルトのデシリアライザがうまく解析する)のための手動解析を書く必要はありません。 – Meatje

+1

@Meatje:カスタムデシリアライザを書く可能性はあると思いますが、それを書く前に、他の解決策はあまり簡単ではないことに注意してください。実際のJSONレスポンスの一部しか含まれていないのですか? – MikO

関連する問題