Как разобрать вложенный список с помощью Retrofit и Gson? - PullRequest
0 голосов
/ 25 февраля 2020

Я делаю учебник по Retrofit с Gson и Rx Java, и в какой-то момент он делает GET-запрос, который возвращает List, единственной конечной точкой, с которой я обращаюсь, являются TMDA и данные, которые мне нужны вложен в JsonObject, поэтому я очень новичок в Gson и Retrofit, поэтому я не знаю, как настроить построитель таким образом, чтобы он анализировал данные внутри вложенного списка, поскольку учебник показывает только то, как он работает напрямую с Список, это код RetrofitConfig:

   @GET("/3/discover/movie?api_key=${apiKey}&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1")
   fun getMovies(): Single<List<Movie>>
}

А вот мой строитель:

 private val api = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build()
        .create(MoviesApi::class.java)

    fun getMovies(): Single<List<Movie>> {
        return api.getMovies()
    }

Вот ответ API:

{
    "page": 1,
    "total_results": 10000,
    "total_pages": 500,
    "results": [
        {
            "popularity": 259.91,
            "vote_count": 366,
            "video": false,
            "poster_path": "/aQvJ5WPzZgYVDrxLX4R6cLJCEaQ.jpg",
            "id": 454626,
            "adult": false,
            "backdrop_path": "/qonBhlm0UjuKX2sH7e73pnG0454.jpg",
            "original_language": "en",
            "original_title": "Sonic the Hedgehog",
            "genre_ids": [
                28,
                35,
                878,
                10751
            ],
            "title": "Sonic the Hedgehog",
            "vote_average": 7.1,
            "overview": "Based on the global blockbuster videogame franchise from Sega, Sonic the Hedgehog tells the story of the world’s speediest hedgehog as he embraces his new home on Earth. In this live-action adventure comedy, Sonic and his new best friend team up to defend the planet from the evil genius Dr. Robotnik and his plans for world domination.",
            "release_date": "2020-02-12"
        },
        {
            "popularity": 253.357,
            "vote_count": 4333,
            "video": false,
            "poster_path": "/7IiTTgloJzvGI1TAYymCfbfl3vT.jpg",
            "id": 496243,
            "adult": false,
            "backdrop_path": "/TU9NIjwzjoKPwQHoHshkFcQUCG.jpg",
            "original_language": "ko",
            "original_title": "기생충",
            "genre_ids": [
                35,
                18,
                53
            ],
            "title": "Parasite",
            "vote_average": 8.6,
            "overview": "All unemployed, Ki-taek's family takes peculiar interest in the wealthy and glamorous Parks for their livelihood until they get entangled in an unexpected incident.",
            "release_date": "2019-05-30"
        },
        {
            "popularity": 213.161,
            "vote_count": 2415,
            "video": false,
            "poster_path": "/xBHvZcjRiWyobQ9kxBhO6B2dtRI.jpg",
            "id": 419704,
            "adult": false,
            "backdrop_path": "/5BwqwxMEjeFtdknRV792Svo0K1v.jpg",
            "original_language": "en",
            "original_title": "Ad Astra",
            "genre_ids": [
                12,
                18,
                9648,
                878,
                53
            ],
            "title": "Ad Astra",
            "vote_average": 6,
            "overview": "The near future, a time when both hope and hardships drive humanity to look to the stars and beyond. While a mysterious phenomenon menaces to destroy life on planet Earth, astronaut Roy McBride undertakes a mission across the immensity of space and its many perils to uncover the truth about a lost expedition that decades before boldly faced emptiness and silence in search of the unknown.",
            "release_date": "2019-09-17"
        },
        {
            "popularity": 171.658,
            "vote_count": 776,
            "video": false,
            "poster_path": "/h4VB6m0RwcicVEZvzftYZyKXs6K.jpg",
            "id": 495764,
            "adult": false,
            "backdrop_path": "/uozb2VeD87YmhoUP1RrGWfzuCrr.jpg",
            "original_language": "en",
            "original_title": "Birds of Prey (and the Fantabulous Emancipation of One Harley Quinn)",
            "genre_ids": [
                28,
                35,
                80
            ],
            "title": "Birds of Prey (and the Fantabulous Emancipation of One Harley Quinn)",
            "vote_average": 6.8,
            "overview": "After her breakup with the Joker, Harley Quinn joins forces with singer Black Canary, assassin Huntress, and police detective Renee Montoya to help a young girl named Cassandra, who had a hit placed on her after she stole a rare diamond from crime lord Roman Sionis.",
            "release_date": "2020-02-05"
        },
        {
            "popularity": 154.297,
            "vote_count": 2258,
            "video": false,
            "poster_path": "/pThyQovXQrw2m0s9x82twj48Jq4.jpg",
            "id": 546554,
            "adult": false,
            "backdrop_path": "/cjTQSwcsfVdirSFSHNBXRGkxmWa.jpg",
            "original_language": "en",
            "original_title": "Knives Out",
            "genre_ids": [
                35,
                80,
                18,
                9648,
                53
            ]

Это похоже на другие фильмы, поэтому при настройке я получаю JsonObject, но он ожидает список, поэтому он выдает ошибку:

 Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

Так что любые идеи о том, как решить эту проблему, будут очень признателен, я очень новичок в этих темах, поэтому извините заранее.

Вот моя модель, так как кто-то спросил

data class Movie(
    val page: Int?,
    val total_results: Int?,
    val total_pages: Int?,
    val results: List<MovieData>
)

data class MovieData(
    val popularity: Int?,
    val vote_count: Int?,
    val video: Boolean?,
    val poster_path: String?,
    val id: Int?,
    val adult: Boolean?,
    val backdrop_path: String?,
    val original_language: String?,
    val original_title: String?,
    val genre_ids: List<Int>?,
    val title: String?,
    val vote_average: Int?,
    val overview: String?,
    val release_date: String?
)

Ответы [ 3 ]

0 голосов
/ 25 февраля 2020

Разобрать ваши данные API json в карту и получить ключ с именем "results". После этого используйте объект mapper для создания массива объекта Mov ie POJO


JsonParser springParser = JsonParserFactory.getJsonParser();
Map<String, Object> map = springParser.parseMap(jsonData);
objectMapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
Movie[] movies = objectMapper.readValue(map.get("results").toString().replace('=', ':'), Movie[].class);


0 голосов
/ 25 февраля 2020

По сути, ваш ответ - объект JSON, когда вы пытаетесь проанализировать его как массив JSON. Класс вашей модели Movie - это ответ, который вы получите. Поэтому, если вы хотите получить полный ответ, используйте

fun getMovies(): Single<Movie>

, это даст вам полный ответ со значением results: List<MovieData> внутри него вместе с другими возвращаемыми параметрами.

Надеюсь, это поможет вам

0 голосов
/ 25 февраля 2020

Вот вам модель ответа, как это,

data class Response(
    @SerializedName("page")
    val page: Int = 0,
    @SerializedName("results")
    val results: List<Result> = listOf(),
    @SerializedName("total_pages")
    val totalPages: Int = 0,
    @SerializedName("total_results")
    val totalResults: Int = 0
) {
    data class Result(
        @SerializedName("adult")
        val adult: Boolean = false,
        @SerializedName("backdrop_path")
        val backdropPath: String = "",
        @SerializedName("genre_ids")
        val genreIds: List<Int> = listOf(),
        @SerializedName("id")
        val id: Int = 0,
        @SerializedName("original_language")
        val originalLanguage: String = "",
        @SerializedName("original_title")
        val originalTitle: String = "",
        @SerializedName("overview")
        val overview: String = "",
        @SerializedName("popularity")
        val popularity: Double = 0.0,
        @SerializedName("poster_path")
        val posterPath: String = "",
        @SerializedName("release_date")
        val releaseDate: String = "",
        @SerializedName("title")
        val title: String = "",
        @SerializedName("video")
        val video: Boolean = false,
        @SerializedName("vote_average")
        val voteAverage: Double = 0.0,
        @SerializedName("vote_count")
        val voteCount: Int = 0
    )
}

Call API, как это,

  @GET("/3/discover/movie?api_key=${apiKey}&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1")
   fun getMovies(): Single<Response<List<Movie>>>
}
...