Вы можете создать собственный десериализатор для этого конкретного случая, или (и этот второй вариант, который я опишу), есть более универсальное c решение, которое требует немного больше усилий, но хорошо окупится в долгосрочной перспективе, как вы могли бы применить его для других подобных случаев использования. Это мой любимый подход, я сталкивался с ним на GitHub (я не изобретатель) - и принял его для себя - вы можете проверить код и проект, чтобы понять, как все это работает вместе - ссылка на проект
Ниже я извлек соответствующие части:
- Создайте специальную фабрику конвертеров следующим образом:
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import okhttp3.ResponseBody
import retrofit2.Converter
import retrofit2.Retrofit
import java.lang.reflect.Type
/**
* A [Converter.Factory] which removes unwanted wrapping envelopes from API
* responses.
*/
class DenvelopingConverter(internal val gson: Gson) : Converter.Factory() {
override fun responseBodyConverter(
type: Type, annotations: Array<Annotation>?, retrofit: Retrofit?): Converter<ResponseBody, *>? {
// This converter requires an annotation providing the name of the payload in the envelope;
// if one is not supplied then return null to continue down the converter chain.
val payloadName = getPayloadName(annotations) ?: return null
val adapter = gson.getAdapter(TypeToken.get(type))
return Converter<ResponseBody, Any> { body ->
try {
val jsonReader = gson.newJsonReader(body.charStream())
jsonReader.beginObject()
while (jsonReader.hasNext()) {
if (payloadName == jsonReader.nextName()) {
return@Converter adapter.read(jsonReader)
} else {
jsonReader.skipValue()
}
}
return@Converter null
} finally {
body.close()
}
}
}
private fun getPayloadName(annotations: Array<Annotation>?): String? {
if (annotations == null) {
return null
}
for (annotation in annotations) {
if (annotation is EnvelopePayload) {
return annotation.value
}
}
return null
}
}
Создать этот класс аннотаций
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.RUNTIME)
annotation class EnvelopePayload(val value: String = "")
В своем модификаторе сборки добавьте преобразователь, созданный на шаге 1
return Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(DenvelopingConverter(gson))
В своем интерфейсе модернизации используйте @EnvelopePayload, который вы создали на шаге 2, чтобы отфильтровать нужные вам элементы, в вашем случае, «статьи», например:
interface MyService {
@EnvelopePayload("articles")
@GET("whatever")
//fun search....
}
Это это, наслаждайтесь!