在 Kotlin 的自定义 JsonDeserializer 中使用默认的 JsonDeserializer

Using default JsonDeserializer inside custom JsonDeserializer in Kotlin

我正在尝试为从 OMDb API 获得的响应构建自定义反序列化器。

这是 Movie 的数据 class:

data class Movie(
    val title: String?,
    val year: String?,
    val imdbID: String?,
    val type: String?,
    val poster: String?,
    val mpaRating: String?,
    val runtime: String?,
    val genres: String?,
    val director: String?,
    val writers: List<String>?,
    val actors: List<String>?,
    val plot: String?,
    val awards: String?,
    val boxOfficeEarnings: String?,
    val ratings: List<Rating>,
    val response: Boolean?
)

对于Rating

data class Rating(
    @SerializedName("Source")
    val source: String,
    @SerializedName("Value")
    val value: String
)

这是目前的习俗JsonDeserializer

class MovieDeserializer : JsonDeserializer<Movie>
{
    override fun deserialize(
        json: JsonElement?,
        typeOfT: Type?,
        context: JsonDeserializationContext?
    ): Movie
    {
        val movieJsonObject = json?.asJsonObject
        return Movie(
            movieJsonObject?.get("Title")?.asString,
            movieJsonObject?.get("Year")?.asString,
            movieJsonObject?.get("imdbID")?.asString,
            movieJsonObject?.get("Type")?.asString,
            movieJsonObject?.get("Poster")?.asString,
            movieJsonObject?.get("Rated")?.asString,
            movieJsonObject?.get("Runtime")?.asString,
            movieJsonObject?.get("Genre")?.asString,
            movieJsonObject?.get("Director")?.asString,
            separateStringByComma(movieJsonObject?.get("Writer")?.asString),
            separateStringByComma(movieJsonObject?.get("Actors")?.asString),
            movieJsonObject?.get("Plot")?.asString,
            movieJsonObject?.get("Awards")?.asString,
            movieJsonObject?.get("BoxOffice")?.asString,
            // this is where I need help,
            movieJsonObject?.get("Response")?.asBoolean
        )
    }

    fun separateStringByComma(stringToSeparate: String?): List<String>?
    {
        return stringToSeparate?.split(", ")
    }
}

如何在不进行一些 json 字符串操作的情况下将该 JsonElement 直接转换为 List<Rating>

顺便说一下,我在 Gson 中使用 Retrofit:

val gsonMovieDeserializer = GsonBuilder()
            .registerTypeAdapter(Movie::class.java, MovieDeserializer())
            .create()
        val retrofit = Retrofit.Builder()
            .baseUrl("https://www.omdbapi.com/")
            .addConverterFactory(GsonConverterFactory.create(gsonMovieDeserializer))
            .build()
        val omdbApi = retrofit.create(OmdbApi::class.java)
        val movie = omdbApi.getMovie(movieImdbId.value.toString())

首先,我想指出可空值的用法:与其在 deserialize() 中的每个调用中检查 movieJsonObject 是否为空,您应该更改函数参数不为 null 然后只检查一次,就在开始时,如果 jsonJsonObject,如果不是,则跳过所有内容。这样,我们就有了提取数据的坚实基础。此外,对于 Movie 数据 class,请查看 API 文档,了解哪些字段是可选的,并且只将它们设置为 nulalble(我很确定至少标题和 ID 总是现在,所以将它们作为 non-nullable).

更有用

现在,对于问题本身,您应该能够使用 context.deserialize<List<Rating>>(movieJsonObject.get("Ratings"), List::class.java) 反序列化该列表,在 Kotlin 中,这将 return a type-safe List<Rating> (但是,再次确保这不是 API 中的可选字段,如果是,则使其可为空)。