我从API获得以下JSON来描述具有不同条目的对象.

{
    "entries": [
        "Simple Text",
        {
            "type": "list",
            "items": [
                "First Item",
                "Second Item",
                "Spectral wings appear on your back, giving you a flying speed of 40 feet."
            ]
        },
        {
            "type": "entries",
            "name": "Sub-Entry",
            "entries": [
                "New text but could also be the same as above"
            ]
        }
    ]
}

在Kotlin中,我希望有一个Entry类,每个类型有一个不同的子类,所以例如EntryText,EntryList,...

由于Json数组的不同元素属于不同的类型,我如何将其解码为类?

问题是多态方法不起作用,因为"简单文本"--条目没有类型.

推荐答案

在正常的序列化发生之前,您可以使用Json transformation来更改您收到的JSON.

本课程:

class EntryPreSerializer : JsonTransformingSerializer<Entry>(Entry.serializer()) {
    override fun transformDeserialize(element: JsonElement): JsonElement {
        return if (element is JsonPrimitive)
            buildJsonObject {
                put("type", JsonPrimitive("StringEntry"))
                put("text", element)
            }
        else element
    }
}

当应用于序列化的Entry对象(我们的多态类)时,它将添加我们在entries中发现JSON原语时进行多态反序列化所需的鉴别器.

为了完成该示例,以下是填充的反序列化的其余部分,包括显示我们如何应用转换:

@Serializable
data class EntryWrapper(val entries: List<@Serializable(with = EntryPreSerializer::class) Entry>)

@Serializable
sealed class Entry

@Serializable
data class StringEntry(val text: String) : Entry()

@Serializable @SerialName("list")
data class ListEntry(val items: List<String>) : Entry()

@Serializable @SerialName("entries")
data class EntriesEntry(val name: String, val entries: List<String>) : Entry()

然后我们可以测试:

fun main() {
    val testJson = """
        {
            "entries": [
                "Simple Text",
                {
                    "type": "list",
                    "items": [
                        "First Item",
                        "Second Item",
                        "Spectral wings appear on your back, giving you a flying speed of 40 feet."
                    ]
                },
                {
                    "type": "entries",
                    "name": "Sub-Entry",
                    "entries": [
                        "New text but could also be the same as above"
                    ]
                }
            ]
        }
    """.trimIndent()
    println(Json.decodeFromString<EntryWrapper>(testJson))
}

它打印:

EntryWrapper(entries=[StringEntry(text=Simple Text), ListEntry(items=[First Item, Second Item, Spectral wings appear on your back, giving you a flying speed of 40 feet.]), EntriesEntry(name=Sub-Entry, entries=[New text but could also be the same as above])])

Json相关问答推荐

在Jenkins中使用ReadJSON读取json子元素

与错误相关的未定义&Quot;不是有效的JSON

使用JQ将对象数组转换为平面数组

nlohmann json:为什么我会得到一个解析错误?

错误:在 NX 工作区中找不到模块../swagger.json

NoneType 对象的 Python 类型错误

Jolt - 如何比较 if else 条件的两个值

用于遮蔽卡的 Jolt 规格

使用 System.Text.Json 序列化记录成员

在 json 嵌入的 YAML 文件中 - 使用 Python 仅替换 json 值

如何在 jQuery 中循环遍历 JSON 数组?

一起使用 Argparse 和 Json

将json字符反序列化为枚举

Jackson Scala 模块的小例子?

Spring restTemplate 获取原始 json 字符串

如何转换为 D3 的 JSON 格式?

JSON 格式的 Amazon S3 响应?

如何从 MySQL 中检索 JSON 数据?

使用 JSON.NET 序列化/反序列化对象字典

jq:按属性分组和键