在 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 然后只检查一次,就在开始时,如果 json
是 JsonObject
,如果不是,则跳过所有内容。这样,我们就有了提取数据的坚实基础。此外,对于 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 中的可选字段,如果是,则使其可为空)。
我正在尝试为从 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 然后只检查一次,就在开始时,如果 json
是 JsonObject
,如果不是,则跳过所有内容。这样,我们就有了提取数据的坚实基础。此外,对于 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 中的可选字段,如果是,则使其可为空)。