2017-01-21 3 views
1

Имея простой интерфейс дооснащенияОпределить Дооснащаемый тип возврата, используя интерфейс вместо класса

interface Movies { 
    @GET("movies/trending") 
    fun trending(): Observable<List<TrendingMovie>> 
} 

Можно ли определить TrendingMovie как интерфейс (результат будет Наблюдаемые список emititng из анонимных классов, реализующих этот интерфейс)?

(я пробовал делать это сделать, но я java.lang.IllegalArgumentException: Нет JsonAdapter для интерфейса com.test.TrendingMovie)

ответ

1

Да, это, безусловно, возможно, но требует, чтобы добавить пользовательский десериализатор для интерфейс. Это делается путем регистрации десериализатора настраиваемого типа для используемого десериализатора.

С Jackson (который я бы рекомендовал использовать для работы с классами Kotlin, в конце концов), это делается путем добавления Module к ObjectMapper. Вот шаги, которые я сделал, чтобы сделать это с jackson-module-kotlin:

  1. Создание пользовательского 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) 
    } 
    
  2. зарегистрировать модуль с ObjectMapper вы используете для Retrofit строитель:

    val mapper = jacksonObjectMapper() 
         .registerModule(trendingMovieModule()) 
    
  3. Используйте 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.

  4. Выполнено! Это должно работать:

    r.trending().flatMap { Observable.from(it) }.forEach(::println) 
    

    Полный исходный файл: (here)

Смежные вопросы