2016-09-22 1 views
1

RxJava와 결합 된 Retrofit 인터페이스가 있습니다. 모든 개조 호출은 Observable을 반환합니다. 그 "SomePojo"클래스는 Schema2Pojo 사이트를 사용하여 온라인으로 생성합니다. 당신이 볼 수 있듯이 https://developers.themoviedb.org/3/search/2Y9y2LReFZdHFHbFA자신의 디시리얼라이저를 구현하는 동안 Gson + AutoValue 오류가 발생했습니다.

, 그것은 개체의 두 가지 다른 유형의 배열은 내가 "미디어"와 "신용"이라는 것이있다 :

나는 다음과 같은 API 호출을 만드는 문제가있다.

@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); 
} 
} 

그리고 : 나는 다음과 같이 구글의 autovalue을 사용하여 생성이 두 클래스

@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 디시리얼라이저 뒤에 주요 아이디어는 : "저기서 신용 객체를 설정 한 다음이 클래스에 대한 기본 유형의 어댑터를 사용하여 deserialize하는 동안 g이 JsonDeserializer을 "

그러나, 어떤 이유로, 나는 다음과 같은 오류가 발생합니다 :

java.lang.RuntimeException가 :에 의해 야기되는 인수 ... 와 공공 미디어()를 호출하지 못했습니다 : java.lang.InstantiationException는 : java.lang.reflect.Constructor.newInstance (기본 방법) 그것은 추상 슈퍼 클래스의 인스턴스를 시도해서는 안

에서 추상 클래스 미디어 를 인스턴스화하지만 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는 다른 모든 TypeAdapters가있는 곳입니다. 나는 개체의 나머지를 역 직렬화하는 데 필요한 유형 어댑터를 제공하지 않습니다

Gson gson = new Gson(); 

를 호출 따라서

.

도움이되기를 바랍니다.

+0

또한 놓친 ... 때때로 우리는 지저분합니다. – box

0

Gson 인스턴스를 만들 때처럼 TypeAdapterFactory를 등록해야합니다. 나를 위해 아래의 대거 2 모듈에서이 작업을 수행했습니다.

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

희망이 도움이됩니다.

관련 문제