VKCOM / vk-android-sdk

Android library for working with VK API, authorization through VK app, using VK functions.
MIT License
457 stars 226 forks source link

java.lang.IllegalStateException: no mapping for the type:audio_playlist при попытке получить список новостей #542

Open tabatsky opened 1 year ago

tabatsky commented 1 year ago

Пытаюсь получить список новостей следующим образом:

VK.execute(NewsfeedService().newsfeedGet(count = 300), object : VKApiCallback<NewsfeedGenericResponseDto> {
  ...
}

Получаю следующую ошибку:

error com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: no mapping for the type:audio_playlist at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) at com.google.gson.Gson.fromJson(Gson.java:932) at com.vk.sdk.api.newsfeed.NewsfeedService.newsfeedGet$lambda$10(NewsfeedService.kt:671) at com.vk.sdk.api.newsfeed.NewsfeedService.$r8$lambda$pl5eceGaftfCY1-KnxwJ_eXUuTk(Unknown Source:0) at com.vk.sdk.api.newsfeed.NewsfeedService$$ExternalSyntheticLambda8.parseResponse(Unknown Source:0) at com.vk.sdk.api.NewApiRequest.parseResponse(Unknown Source:7) at com.vk.sdk.api.NewApiRequest.parse(NewApiRequest.kt:48) at com.vk.api.sdk.chain.MethodChainCall.parseResult(MethodChainCall.kt:98) at com.vk.api.sdk.chain.MethodChainCall.runRequest(MethodChainCall.kt:82) at com.vk.api.sdk.chain.MethodChainCall.call(MethodChainCall.kt:78) at com.vk.api.sdk.chain.ValidationHandlerChainCall.call(ValidationHandlerChainCall.kt:45) at com.vk.api.sdk.chain.ApiMethodPriorityChainCall.call(ApiMethodPriorityChainCall.kt:28) at com.vk.api.sdk.chain.InvalidCredentialsObserverChainCall.callWithAuthCheck(InvalidCredentialsObserverChainCall.kt:45) at com.vk.api.sdk.chain.InvalidCredentialsObserverChainCall.call(InvalidCredentialsObserverChainCall.kt:41) at com.vk.api.sdk.chain.TooManyRequestRetryChainCall.call(TooManyRequestRetryChainCall.kt:46) at com.vk.api.sdk.chain.RateLimitReachedChainCall.call(RateLimitReachedChainCall.kt:34) at com.vk.api.sdk.chain.SectionTemporaryUnavailableChainCall.call(SectionTemporaryUnavailableChainCall.kt:23) at com.vk.api.sdk.chain.InternalErrorChainCall.call(InternalErrorChainCall.kt:23) at com.vk.api.sdk.chain.ErrorRetryChainCall.call(ErrorRetryChainCall.kt:47) at com.vk.api.sdk.VKApiManager.executeWithExceptionAdjust(VKApiManager.kt:163) at com.vk.api.sdk.VKApiManager.execute(VKApiManager.kt:112) at com.vk.api.sdk.requests.VKRequest.onExecute(VKRequest.kt:112) at com.vk.api.sdk.internal.ApiCommand.execute(ApiCommand.kt:46) at com.vk.api.sdk.VK.executeSync(VK.kt:201) at com.vk.api.sdk.VK.execute$lambda$4(VK.kt:213) at com.vk.api.sdk.VK.$r8$lambda$thDoqhqvvqs8RMBZj0ShwHF6oJY(Unknown Source:0) at com.vk.api.sdk.VK$$ExternalSyntheticLambda0.run(Unknown Source:4) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:463) at java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637) at java.lang.Thread.run(Thread.java:1012) Caused by: java.lang.IllegalStateException: no mapping for the type:audio_playlist at com.vk.sdk.api.newsfeed.dto.NewsfeedNewsfeedItemDto$Deserializer.deserialize(NewsfeedNewsfeedItemDto.kt:1862) at com.vk.sdk.api.newsfeed.dto.NewsfeedNewsfeedItemDto$Deserializer.deserialize(NewsfeedNewsfeedItemDto.kt:1844) at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:69) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)  at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)  at com.google.gson.Gson.fromJson(Gson.java:932)  at com.vk.sdk.api.newsfeed.NewsfeedService.newsfeedGet$lambda$10(NewsfeedService.kt:671)  at com.vk.sdk.api.newsfeed.NewsfeedService.$r8$lambda$pl5eceGaftfCY1-KnxwJ_eXUuTk(Unknown Source:0)  at com.vk.sdk.api.newsfeed.NewsfeedService$$ExternalSyntheticLambda8.parseResponse(Unknown Source:0)  at com.vk.sdk.api.NewApiRequest.parseResponse(Unknown Source:7)  at com.vk.sdk.api.NewApiRequest.parse(NewApiRequest.kt:48)  at com.vk.api.sdk.chain.MethodChainCall.parseResult(MethodChainCall.kt:98)  at com.vk.api.sdk.chain.MethodChainCall.runRequest(MethodChainCall.kt:82)  at com.vk.api.sdk.chain.MethodChainCall.call(MethodChainCall.kt:78)  at com.vk.api.sdk.chain.ValidationHandlerChainCall.call(ValidationHandlerChainCall.kt:45)  at com.vk.api.sdk.chain.ApiMethodPriorityChainCall.call(ApiMethodPriorityChainCall.kt:28)  at com.vk.api.sdk.chain.InvalidCredentialsObserverChainCall.callWithAuthCheck(InvalidCredentialsObserverChainCall.kt:45)  at com.vk.api.sdk.chain.InvalidCredentialsObserverChainCall.call(InvalidCredentialsObserverChainCall.kt:41)  at com.vk.api.sdk.chain.TooManyRequestRetryChainCall.call(TooManyRequestRetryChainCall.kt:46)  at com.vk.api.sdk.chain.RateLimitReachedChainCall.call(RateLimitReachedChainCall.kt:34)  at com.vk.api.sdk.chain.SectionTemporaryUnavailableChainCall.call(SectionTemporaryUnavailableChainCall.kt:23)  at com.vk.api.sdk.chain.InternalErrorChainCall.call(InternalErrorChainCall.kt:23)  at com.vk.api.sdk.chain.ErrorRetryChainCall.call(ErrorRetryChainCall.kt:47)  at com.vk.api.sdk.VKApiManager.executeWithExceptionAdjust(VKApiManager.kt:163)  at com.vk.api.sdk.VKApiManager.execute(VKApiManager.kt:112)  at com.vk.api.sdk.requests.VKRequest.onExecute(VKRequest.kt:112)  at com.vk.api.sdk.internal.ApiCommand.execute(ApiCommand.kt:46)  at com.vk.api.sdk.VK.executeSync(VK.kt:201)  at com.vk.api.sdk.VK.execute$lambda$4(VK.kt:213)  at com.vk.api.sdk.VK.$r8$lambda$thDoqhqvvqs8RMBZj0ShwHF6oJY(Unknown Source:0)  at com.vk.api.sdk.VK$$ExternalSyntheticLambda0.run(Unknown Source:4)  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:463)  at java.util.concurrent.FutureTask.run(FutureTask.java:264)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)  at java.lang.Thread.run(Thread.java:1012) 

tabatsky commented 1 year ago

Я исправил ошибку, заменив некоторые классы и функции на свои собственные, и понизив версию API в NewApiRequest до 5.81.

fun newsfeedGet(
    filters: List<NewsfeedNewsfeedItemTypeDto>? = null,
    returnBanned: Boolean? = null,
    startTime: Int? = null,
    endTime: Int? = null,
    maxPhotos: Int? = null,
    sourceIds: String? = null,
    startFrom: String? = null,
    count: Int? = null,
    fields: List<BaseUserGroupFieldsDto>? = null,
    section: String? = null
): VKRequest<NewsfeedGenericResponseDto> = NewApiRequest<NewsfeedGenericResponseDto>("newsfeed.get") {
    GsonHolder.gson.parse(it)
}
    .apply {
        val filtersJsonConverted = filters?.map {
            it.value
        }
        filtersJsonConverted?.let { addParam("filters", it) }
        returnBanned?.let { addParam("return_banned", it) }
        startTime?.let { addParam("start_time", it, min = 0) }
        endTime?.let { addParam("end_time", it, min = 0) }
        maxPhotos?.let { addParam("max_photos", it, min = 0) }
        sourceIds?.let { addParam("source_ids", it) }
        startFrom?.let { addParam("start_from", it) }
        count?.let { addParam("count", it, min = 0) }
        val fieldsJsonConverted = fields?.map {
            it.value
        }
        fieldsJsonConverted?.let { addParam("fields", it) }
        section?.let { addParam("section", it) }
    }

private class NewApiRequest<T> constructor(
    methodName: String,
    parser: ApiResponseParser<T>
) : VKRequest<T>(methodName, requestApiVersion = "5.81"), ApiResponseParser<T> by parser {
    override fun parse(responseJson: JSONObject): T =
        parseResponse(JsonTreeReader(JsonParser.parseString(responseJson.toString())))

    fun addParam(
        name: String,
        value: String?,
        minLength: Int = 0,
        maxLength: Int = Int.MAX_VALUE
    ) {
        if (value != null) {
            if (value.length !in minLength..maxLength) {
                throw IllegalArgumentException("Param $name not in $minLength..$maxLength")
            }
            params[name] = value
        }
    }

    fun addParam(
        name: String,
        value: Int,
        min: Int = Int.MIN_VALUE,
        max: Int = Int.MAX_VALUE
    ) {
        if (value !in min..max) {
            throw IllegalArgumentException("Param $name not in $min..$max")
        }
        params[name] = value.toString()
    }

    fun addParam(
        name: String,
        value: Long,
        min: Long = Long.MIN_VALUE,
        max: Long = Long.MAX_VALUE
    ) {
        if (value !in min..max) {
            throw IllegalArgumentException("Param $name not in $min..$max")
        }
        params[name] = value.toString()
    }

    fun addParam(
        name: String,
        value: Float,
        min: Double = -Double.MAX_VALUE,
        max: Double = Double.MAX_VALUE
    ) {
        if (value !in min..max) {
            throw IllegalArgumentException("Param $name not in $min..$max")
        }
        params[name] = value.toString()
    }

    fun addParam(
        name: String,
        value: UserId?,
        min: Long = Long.MIN_VALUE,
        max: Long = Long.MAX_VALUE
    ) {
        if (value != null) {
            if (value.value !in min..max) {
                throw IllegalArgumentException("Param $name not in $min..$max")
            }
            params[name] = value.value.toString()
        }
    }

    fun addParam(
        name: String,
        values: List<UserId>,
        min: Long = Long.MIN_VALUE,
        max: Long = Long.MAX_VALUE
    ) {
        addParam(name, values.joinToString(",", transform =  {
            if (it.value !in min..max) {
                throw IllegalArgumentException("Param $name not in $min..$max")
            }
            it.value.toString()
        }
        ))
    }
}

private fun interface ApiResponseParser<T> {
    fun parseResponse(jsonReader: JsonReader): T
}

private inline fun <reified T> Gson.parse(reader: JsonReader): T =
    fromJson<RootResponseDto<T>>(reader, TypeToken.getParameterized(
        RootResponseDto::class.java,
        T::class.java).type).response

private data class RootResponseDto<T>(
    @SerializedName("response")
    val response: T
)