【问题标题】:Deserialize generic object using Kotlin Serialization使用 Kotlin 序列化反序列化通用对象
【发布时间】:2020-11-18 16:01:22
【问题描述】:

我正在尝试用 kotlin serialization 替换 Gson 库来处理 JSON 序列化/反序列化。

我在反序列化通用对象时遇到了一些问题我已经设置了一个我想要实现的简单示例:

@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")

}

但是当我运行 main 方法时,我得到以下错误:

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)

但我不知道为什么。有人可以给我一个解释,如果可能的话,我可以提供一些关于如何实现这一点的提示吗?

【问题讨论】:

    标签: kotlin generics serialization json-deserialization


    【解决方案1】:

    如果你只是这样做,它会起作用的:

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

    但是由于所有这些包装,有关T 的类型信息丢失了。问题是你不能在这里简单地使用reified 泛型,因为inline 函数不能是非最终的。

    可能的解决方法:

    1. parseContentMessage定义为扩展函数,这样它就可以有inline修饰符(而T可以是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. 手动将T 的序列化程序传递给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())
    
    

    【讨论】:

    • 感谢您的建议。我知道是我直接打电话会奏效的。有时间我会试试你的建议
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多