2016-09-22 3 views
1

私はRxJavaと組み合わされたRetrofitインターフェイスを持っています。すべての私の改造呼び出しはObservableを返します。それらの "SomePojo"クラス、私はそれらをSchema2Pojoサイトを使ってオンラインで生成します。自分自身のデシリアライザを実装しようとしているときにGson + AutoValueエラーが発生しました

次のAPI呼び出し作るとき、私は問題を抱えている:あなたが見ることができるように https://developers.themoviedb.org/3/search/2Y9y2LReFZdHFHbFA

を、それは私が「メディア」と呼ばれ、「信用」という、オブジェクトの二つの異なるタイプの配列です。

@AutoValue 
public abstract class Media implements Parcelable { 

@SerializedName(value = "title", alternate = {"name"}) 
public abstract String title(); 

@Nullable 
@SerializedName("vote_average") 
public abstract String voteAverage(); 

@Nullable 
@SerializedName("backdrop_path") 
public abstract String backdropPath(); 

@Nullable 
public abstract String adult(); 

public abstract String id(); 

@Nullable 
public abstract String overview(); 

@Nullable 
@SerializedName("original_language") 
public abstract String originalLanguage(); 

@Nullable 
@SerializedName("genre_ids") 
public abstract List<String> genreIds(); 

@Nullable 
@SerializedName(value = "release_date", alternate = {"first_air_date"}) 
public abstract String releaseDate(); 

@Nullable 
@SerializedName(value = "original_title", alternate = {"original_name"}) 
public abstract String originalTitle(); 

@Nullable 
@SerializedName("vote_count") 
public abstract String voteCount(); 

@Nullable 
@SerializedName("poster_path") 
public abstract String posterPath(); 

@Nullable 
public abstract String video(); 

@Nullable 
@SerializedName("media_type") 
public abstract String mediaType(); 

@Nullable 
public abstract String popularity(); 

@Nullable 
@SerializedName("origin_country") 
public abstract List<String> originalCountry(); 


public static Media create(String title, String voteAverage, String backdropPath, 
          String adult, String id, String overview, String originalLanguage, 
          List<String> genreIds, String releaseDate, String originalTitle, 
          String voteCount, String posterPath, String video, String mediaType, 
          String popularity, List<String> originalCountry) { 

    return new AutoValue_Media(title, voteAverage, backdropPath, adult, id, overview, 
      originalLanguage, genreIds, releaseDate, originalTitle, voteCount, posterPath, 
      video, mediaType, popularity, originalCountry); 
} 

public static TypeAdapter<Media> typeAdapter(Gson gson) { 
    return new AutoValue_Media.GsonTypeAdapter(gson); 
} 
} 

そして:私は次のようにGoogleの自動入力値を使用して生成されたこれらの二つのクラス

@AutoValue 
public abstract class Credit implements Parcelable { 
public abstract String id(); 

@SerializedName("credit_id") 
public abstract String creditId(); 

@Nullable 
public abstract String department(); 

public abstract String name(); 

@Nullable 
@SerializedName(value = "job", alternate = {"character"}) 
public abstract String job(); 

@Nullable 
@SerializedName("profile_path") 
public abstract String profilePath(); 

@Nullable 
public abstract String order(); 

@Nullable 
@SerializedName("cast_id") 
public abstract String castId(); 


public static Credit create(String id, String creditId, String department, String name, String job, 
          String profilePath, String order, String castId) { 

    return new AutoValue_Credit(id, creditId, department, name, job, profilePath, order, castId); 
} 

public static TypeAdapter<Credit> typeAdapter(Gson gson) { 
    return new AutoValue_Credit.GsonTypeAdapter(gson); 
} 

} 

をオブジェクトの二つの異なる種類の配列が作成した問題を解決するには、私はこの呼び出しによってPOJOのリターンを作りました独自のJsonDeserializerを実装:

public class MediaListPojo { 

    @SerializedName("results") 
    private List<Media> movies; 

    private List<Credit> credits; 

    private Dates dates; 

    private String page; 

    private String total_pages; 

    private String total_results; 

    public List<Media> getMedia() { 
     return movies; 
    } 

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

    public List<Credit> getCredits() {return credits;} 

    public void setCredits(List<Credit> credits) {this.credits = credits;} 

    public Dates getDates() { 
     return dates; 
    } 

    public void setDates(Dates dates) { 
     this.dates = dates; 
    } 

    public String getPage() { 
     return page; 
    } 

    public void setPage(String page) { 
     this.page = page; 
    } 

    public String getTotal_pages() { 
     return total_pages; 
    } 

    public void setTotal_pages(String total_pages) { 
     this.total_pages = total_pages; 
    } 

    public String getTotal_results() { 
     return total_results; 
    } 

    public void setTotal_results(String total_results) { 
     this.total_results = total_results; 
    } 

    @Override 
    public String toString() { 
     return "MediaListPojo{" + 
       "movies=" + movies + 
       ", credits=" + credits + 
       ", dates=" + dates + 
       ", page='" + page + '\'' + 
       ", total_pages='" + total_pages + '\'' + 
       ", total_results='" + total_results + '\'' + 
       '}'; 
    } 

    public static class MediaListPojoDeserializer implements JsonDeserializer<MediaListPojo> { 

     @Override 
     public MediaListPojo deserialize(JsonElement json, Type typeOfT, 
             JsonDeserializationContext context) throws JsonParseException { 

      MediaListPojo mediaListPojo = new Gson().fromJson(json, MediaListPojo.class); 
      JsonObject jsonObject = json.getAsJsonObject(); 

      if (jsonObject.has("results")) { 
       JsonArray jsonArray = jsonObject.getAsJsonArray("results"); 
       List<Credit> credits = new ArrayList<>(); 
       Credit credit; 
       for (JsonElement element : jsonArray) { 
        JsonObject current = element.getAsJsonObject(); 

        if (current.get("media_type").getAsString().equals("person")) { 
         credit = new Gson().fromJson(current, Credit.class); 
         credits.add(credit); 
        } 
       } 
       mediaListPojo.setCredits(credits); 
      } 
      return mediaListPojo; 
     } 
    } 
} 

このJSONデシリアライザの背後にある主な考え方は次のとおりです。「usinクレジットオブジェクトを設定し、このクラスのデフォルトのタイプのアダプタを使用し、デシリアライズしながら、グラムこのJsonDeserializer」を

しかし、何らかの理由で、私は次のエラーを取得する:

java.lang.RuntimeException:によって引き起こさなし引数 ... と公共メディアを()呼び出しに失敗しました: java.lang.InstantiationException:抽象クラスのインスタンス化を試みるべきではありません。AutoValueの生成された型アダプタを使用して抽象スーパークラスをインスタンス化しようとするべきではありません。

これは私が私の改造インスタンスを構築しました方法です:

class Creator { 

    public static MovieService newMovieService() { 
     Gson gson = new GsonBuilder() 
       .registerTypeAdapterFactory(new AutoValueGson_MyAdapterFactory()) 
       .registerTypeAdapter(MediaListPojo.class, new MediaListPojo.MediaListPojoDeserializer()) 
       .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") 
       .create(); 
     OkHttpClient client = new OkHttpClient.Builder() 
       .addInterceptor(NetworkUtil.makeQueryInterceptor("api_key", BuildConfig.MY_API_KEY)) 
       .build(); 
     Retrofit retrofit = new Retrofit.Builder() 
       .client(client) 
       .baseUrl(MovieService.ENDPOINT) 
       .addConverterFactory(GsonConverterFactory.create(gson)) 
       .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
       .build(); 
     return retrofit.create(MovieService.class); 

あなたは私が私が間違って何をしたか理解するのに役立つことはできますか?

答えて

2

質問を投稿して5分後に私は解決策を見つけましたが、他の人もこれと闘うかもしれないと思っています。

基本的に私のJsonDeserializerの中で、私はGsonオブジェクトの新しいインスタンスを使用していましたが、実際にはこれは間違いです。

私のレトロフィットインスタンスの作成中に登録したtypeadapterfactoryは、他のTypeAdapterがすべて存在する場所です。

したがって、

Gson gson = new Gson(); 

を呼び出すと、私は、オブジェクトの残りの部分をデシリアライズするために必要なタイプのアダプタを提供していません。

私はそれが役に立ちそうです。

+0

それも見逃してしまった...時々、私たちはたるんでいる。 – box

0

Gsonのインスタンスを作成するときにTypeAdapterFactoryを登録する必要があります。私のために私は以下のような私のダガー2モジュールでこれをしました。

Gson gson = new GsonBuilder() 
      .registerTypeAdapterFactory(GsonAdapterFactory.create()) 
      .create(); 

これが役に立ちます。

関連する問題