Ich habe eine Retrofit-Schnittstelle, die ich mit RxJava kombinieren. Alle meine Retrofit-Anrufe kehren Observable zurück. Diese "SomePojo" -Klassen erzeuge ich online mithilfe von Schema2Pojo-Sites.Gson + AutoValue Fehler beim Versuch, eigene Deserializer zu implementieren
Ich habe ein Problem, wenn der folgenden api Anruf: https://developers.themoviedb.org/3/search/2Y9y2LReFZdHFHbFA
Wie Sie sehen, es ist ein Array mit zwei unterschiedlichen Typen von Objekten, die ich „Medien“ und „Credit“ genannt. Diese beiden Klassen I erzeugt mit Googles Autowert wie folgt:
@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);
}
}
Und:
@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);
}
}
das Problem durch die Anordnung mit zwei verschiedenen Arten von Objekten erstellt zu beheben, habe ich die POJO Rückkehr von diesem Aufruf seine eigenen JsonDeserializer implementieren:
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;
}
}
}
die Grundidee hinter diesem json Deserializer ist: „für diese Klasse des Standardtyp Adapter verwenden und dann die Kredite Objekte festgelegt usin g dieses JsonDeserializer“
jedoch aus irgendeinem Grund bekomme ich folgende Fehler beim Deserialisieren:
java.lang.RuntimeException: Fehler mit den öffentlichen Medien() ohne args ... verursacht aufzurufen: java.lang.InstantiationException: Kann nicht abstrakte Klasse Medien bei java.lang.reflect.Constructor.newInstance (Mutter Methode)
instanziiert Es sollte nicht die abstrakte Superklasse zu instanziiert versuchen, aber der Autovalue generiert Typ Adapter verwenden. Diese
ist, wie ich meine Retrofit Instanz gebaut:
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);
Können Sie mir helfen, zu verstehen, was ich falsch gemacht habe?
Verpasste auch ... manchmal sind wir schlampig. – box