具有简单的Retrofit界面
interface Movies {
@GET("movies/trending")
fun trending(): Observable<List<TrendingMovie>>
}
是否可以将TrendingMovie定义为接口(结果将是Observable emititng实现此接口的匿名类列表)?
(我试过这样做,但我得到java.lang.IllegalArgumentException:没有JsonAdapter用于接口com.test.TrendingMovie)
答案 0 :(得分:1)
是的,这肯定是可能的,但要求您为界面添加自定义反序列化器。这是通过为您使用的反序列化工具注册自定义类型反序列化器来完成的。
有了杰克逊(毕竟我会推荐用于与Kotlin课程一起工作),这是通过向Module
添加ObjectMapper
来完成的。以下是我使用jackson-module-kotlin
执行此操作的步骤:
为您的界面添加Module
创建自定义JsonDeserializer
:
fun trendingMovieModule(): Module = SimpleModule().apply {
val deserializer: JsonDeserializer<TrendingMovie> = object : JsonDeserializer<TrendingMovie>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): TrendingMovie {
val node = p.codec.readTree<JsonNode>(p)
return object : TrendingMovie { // Your anonymous class here, for example:
val name = node["movie"]["title"]
val watchers = node["watchers"].intValue()
override fun toString(): String = "$name, watchers: $watchers"
}
}
}
addDeserializer(TrendingMovie::class.java, deserializer)
}
使用ObjectMapper
构建器Retrofit
注册模块:
val mapper = jacksonObjectMapper()
.registerModule(trendingMovieModule())
使用mapper
构建器中的Retrofit
:
val r = Retrofit.Builder()
// other necessary configuration omitted, e.g. custom OkHttpClient
.baseUrl("https://api.trakt.tv")
.addConverterFactory(JacksonConverterFactory.create(mapper))
.build().create(Movies::class.java)
JacksonConverterFactory
需要依赖:converter-jackson
。
完成!它现在应该工作:
r.trending().flatMap { Observable.from(it) }.forEach(::println)
完整的源文件:(here)