Search code examples
androidjsonkotlinretrofit2jetbrains-ide

What are some possible causes of this Kotlin Retrofit2 error?


What are some possible causes of this Kotlin Retrofit2 error? My JSON was converting correctly when I had coded this using enqueue. I updated it to use Deferred and Response and I'm now getting this error.

Unable to create converter for kotlinx.coroutines.Deferred<retrofit2.Response<com.smate.data.apiResponse.GenericApiResponse>>

It refers to this section of my code:

@Headers("Content-Type: application/json")
@POST("validIdentification")
suspend fun isValidIdentificationAsync(@Body identification: Identification): Deferred<Response<GenericApiResponse>>

Here's the GenericApiResponse class:

package com.smate.data.apiResponse

import kotlinx.serialization.Serializable

@Serializable
data class GenericApiResponse(
    var isValid:String
) {
    val isValidBoolean: Boolean
        get() = isValid.toBoolean()
}

This is the calling function:

override suspend fun isValidIdentification(identification: Identification): ValidationResult {
    try {
        val response = sMateApiService.isValidIdentificationAsync(identification).await()
        if (response.isSuccessful) {
            val genericResponse: GenericApiResponse? = response.body()
            if (genericResponse != null) {
                return ValidationResult.Success(genericResponse.isValidBoolean)
            }
        } else {
            return ValidationResult.Error("API call failed")
        }
    } catch (e: Exception) {
        return ValidationResult.Error("An error occurred: ${e.message}")
    }

    return ValidationResult.Error("Unexpected error")
}

I'm implementing these in my gradle file:

implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0"

Solution

  • In Kotlin coroutines, Deferred is a type of Job representing an ongoing coroutine. I think Retrofit has support for Deferred, though I do not recall using it.

    Retrofit definitely has support for suspend fun, which also has the work be done via a coroutine.

    Your code is attempting to use both: the function is declared as suspend fun and it is returning a Deferred. That seems unnecessary, as you should only need one to represent that the work should be executed in a coroutine.

    As discussed in question comments, you removed the Deferred and the problem went away. Because of the suspend fun, your network I/O still will be performed in a coroutine, using Retrofit's default dispatcher.