Martin Gaens
07/06/2022, 11:15 PMJsonContentPolymorphicSerializer
for the following class hierarchy? I want it to select the proper serializer by checking the value of the "ok" key in the JSON and if it's true, return a ApiResponse.Success
serializer and if false return the ApiResponse.Error
serializer.
@Serializable
internal sealed class ApiResponse {
@SerialName("ok") abstract val ok: Boolean
@Serializable
class Success<T>(
override val ok: Boolean,
@SerialName("result") val result: T
) : ApiResponse()
@Serializable
class Error(
override val ok: Boolean,
@SerialName("error_code") val errorCode: Int,
@SerialName("description") val description: String
) : ApiResponse()
}
ephemient
07/06/2022, 11:35 PMclass ApiResponseSerializer<T>(
private val tSerializer: KSerializer<T>,
) : JsonContentPolymorphicSerializer<ApiResponse>(ApiResponse::class) {
override fun selectDeserializer(content: JsonElement) = when {
"result" in content.jsonObject -> ApiResponse.Success.serializer(tSerializer)
else -> ApiResponse.Error.serialier()
}
}
?Martin Gaens
07/06/2022, 11:50 PMApiResponse
class as well. This is what the updated ApiResponse
class looks like:
@Serializable
internal sealed class ApiResponse<T> {
@SerialName("ok") abstract val ok: Boolean
@Serializable
class Success<T>(
override val ok: Boolean,
@SerialName("result") val result: T
) : ApiResponse<T>()
@Serializable
class Error<T>(
override val ok: Boolean,
@SerialName("error_code") val errorCode: Int,
@SerialName("description") val description: String
) : ApiResponse<T>()
}
Now, the code you proposed doesn't work anymore because I can't pass a KClass<T>
into the constructor of JsonContentPolymorphicSerializer
.ephemient
07/06/2022, 11:56 PMMartin Gaens
07/07/2022, 12:02 AMApiResponse
class but I wanted to do fancy stuff like this which would be otherwise not possible:
when (val apiResponse = response.body<ApiResponse<List<UpdateDto>>>()) {
is ApiResponse.Success -> return apiResponse.result.map { it.toEntity() }
is ApiResponse.Error -> error(
"""
Got an error response from the getUpdates method which should be impossible.
Error code: ${apiResponse.errorCode}
Description: ${apiResponse.description}
""".trimIndent()
)
}
ephemient
07/07/2022, 12:05 AMsealed class ApiResponse<out T> {
data class Ok<out T>(val value: T) : ApiResponse<T>()
data class Err(val message: String) : ApiResponse<Nothing>()
}
but unfortunately that doesn't play well with serialization https://github.com/Kotlin/kotlinx.serialization/issues/614 😞Martin Gaens
07/07/2022, 12:10 AMephemient
07/07/2022, 12:11 AMJsonContentPolymorphicSerializer
:-/Martin Gaens
07/07/2022, 12:18 AMephemient
07/07/2022, 12:23 AMMartin Gaens
07/07/2022, 9:29 AMkotlinx.serialization
would pass automatically for you an instance of KSerializer<T> into the constructor of my serializer. The more ya know! Here's my final code in case somebody needs it. And thanks again, @ephemient, for your super quick responses.