8

I am trying to replace Gson library by kotlin serialization to handle JSON serialization/deserialization.

I am facing some issues to deserialize generic objects I have setup a simple example of what I am trying to achieve:

@Serializable
data class ContentMessageDto<T>(
    val method: String,
    val content: T
)

@Serializable
private data class DummyObjectNonNullProperties(
    val value: Int,
    @SerialName("aaa") val someProp: String,
    val bbb: Boolean,
    val ccc: Double
)

interface MyParser {
    fun <T> parseContentMessage(
        json: String
    ): ContentMessageDto<T>
}

class MyParserImpl(private val jsonSerialization: Json) : MyParser {
    override fun <T> parseContentMessage(json: String): ContentMessageDto<T> {
        return jsonSerialization.decodeFromString<ContentMessageDto<T>>(json)
    }

}

fun main() {
    println("start processing...")
    val jsonToParse = """
                {
                    "method":"get",
                    "content":{
                        "value":345,
                        "aaa": "some string",
                        "bbb": true,
                        "ccc": 23.4
                    }
                }""".trimIndent()

    val parser:MyParser = MyParserImpl(Json)

    val result = parser.parseContentMessage<DummyObjectNonNullProperties>(jsonToParse)

    println("result -> $result")

}

But when I run the main method, I get the following error:

Exception in thread "main" java.lang.IllegalStateException: Only KClass supported as classifier, got T
    at kotlinx.serialization.internal.Platform_commonKt.kclass(Platform.common.kt:102)
    at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:52)
    at kotlinx.serialization.SerializersKt.serializer(Unknown Source)
    at kotlinx.serialization.SerializersKt__SerializersKt.builtinSerializerOrNull$SerializersKt__SerializersKt(Serializers.kt:79)
    at kotlinx.serialization.SerializersKt__SerializersKt.serializerByKTypeImpl$SerializersKt__SerializersKt(Serializers.kt:69)
    at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:54)
    at kotlinx.serialization.SerializersKt.serializer(Unknown Source)

But I am not sure why. Can someone provide me an explanation and if possible some tips on how I can implement this?

1 Answer 1

6

It would have worked if you've simply done:

val result = Json.decodeFromString<ContentMessageDto<DummyObjectNonNullProperties>>(jsonToParse)

But with all this wrapping, type information about T was lost. The problem is that you can't simply use reified generics here, cause inline functions can't be non-final.

Possible workarounds:

  1. Define parseContentMessage as extension function so that it could have inline modifier (and T could be reified):
interface MyParser {
    val jsonSerialization: Json
}

inline fun<reified T> MyParser.parseContentMessage(json: String): ContentMessageDto<T> {
    return jsonSerialization.decodeFromString(json)
}

class MyParserImpl(override val jsonSerialization: Json) : MyParser

//Usage will be the same
  1. Manually pass serializer for T into parseContentMessage:
interface MyParser {
    fun <T> parseContentMessage(json: String, contentSerializer: KSerializer<T>): ContentMessageDto<T>
}

class MyParserImpl(private val jsonSerialization: Json) : MyParser {
    override fun <T> parseContentMessage(json: String, contentSerializer: KSerializer<T>): ContentMessageDto<T> {
        return jsonSerialization.decodeFromString(ContentMessageDto.serializer(contentSerializer), json)
    }
}

//Usage:
val result = parser.parseContentMessage(jsonToParse, DummyObjectNonNullProperties.serializer())

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the suggestion. I know is I call directly it would have worked. When I find some time I will try your suggestions
What if T could be also a String or a Boolean?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.