如何将 JSON 字符串解码为给定的 KClass?

Posted

技术标签:

【中文标题】如何将 JSON 字符串解码为给定的 KClass?【英文标题】:How to decode a JSON string to a given KClass? 【发布时间】:2022-01-06 21:03:41 【问题描述】:

我的代码结构是这样的:

文件 1:

abstract class SomeClass 
    abstract fun print()

    companion object 
        val versions = arrayOf(ClassV1::class, ClassV2::class)
    


@Serializable
data class ClassV1(val x: Int) : SomeClass() 
    override fun print() 
        println("Hello")
    


@Serializable
data class ClassV2(val y: String) : SomeClass() 
    override fun print() 
        println("World")
    

文件 2:

fun <T : SomeClass> getSomeObject(json: String, kClass: KClass<T>): SomeClass 
    return Json.decodeFromString(json)


fun printData(version: Int, json: String) 
    val someClass: SomeClass = getSomeObject(json, SomeClass.versions[version])
    someClass.print()

我在printData 中有一个json,它是SomeClass 的某个子类的序列化形式。我还有一个version,用于确定json 代表的类结构。基于version,我想将我的json字符串反序列化为SomeClass的适当子类。

现在 getSomeObject 函数将 json 反序列化为 SomeClass(如预期的那样崩溃)。我想知道是否有办法将其反序列化为提供的KClass

我知道我可以这样做:

val someClass = when (version) 
    0 -> Json.decodeFromString<ClassV1>(json)
    else -> Json.decodeFromString<ClassV2>(json)

但我试图避免这种情况,因为我可以有很多这样的版本。有没有更好的办法?

【问题讨论】:

这有帮助吗? github.com/Kotlin/kotlinx.serialization/blob/master/docs/… @dnault 我浏览了那个文档。无法理解整个事情,但看起来它肯定比 when 声明更有效。 @ArpitShukla 您正在尝试进行多态序列化。如果您想这样做,您将需要理解/阅读该文档。这基本上是你的答案。如果您不了解该文档的某些内容,可以将您的问题集中在 。附:不,这并不比when 声明更多的工作。 kotlinx.serializationSerializersModule 本质上等同于(逻辑上)when 语句。 【参考方案1】:

在我看来,您正在寻找以下内容:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "version",
    visible = false)
@JsonSubTypes(
    JsonSubTypes.Type(value = ClassV1::class, name = "V1"),
    JsonSubTypes.Type(value = ClassV2::class, name = "V2"))
abstract class SomeClass 
    (...)
  

这基本上意味着您的 JSON 将根据 JSON 属性 version 反序列化为 ClassV1ClassV2

V1 表示ClassV1 是目标类; V2 表示ClassV2 是目标类。

您可以在以下在线资源中找到更多相关信息:

https://fasterxml.github.io/jackson-annotations/javadoc/2.4/com/fasterxml/jackson/annotation/JsonTypeInfo.html https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonSubTypes.Type.html https://www.baeldung.com/jackson-annotations#jackson-polymorphic-type-handling-annotations

【讨论】:

感谢您的回答。我想知道是否可以使用 kotlinx.serialization 来做到这一点,因为我在一个项目中负担不起多个 json 解析库。但在这里我也必须为所有versions 指定JsonSubTypes.Type。我想我会采用我之前的 when 方法。 kotlinx.serialization 我不知道有什么方法可以做到这一点,但也许是可能的。 这是给 Jackson 的。 OP正在询问kotlinx.serialization。 -1

以上是关于如何将 JSON 字符串解码为给定的 KClass?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 json 字符串解码为 UTF-8?

如何将 JSON 解码为不同的类型?

如何修复“JSONDecodeError:无法解码 JSON 对象:第 1 行第 0 列(字符 0)”?

无法解码有效的 json 格式,响应内容必须是实现 __toString() 的字符串或对象,给定的“对象”

Php json将所有值解码为字符串

将 HTML 编码为有效的 JSON