0

在我使用 kotlin-react 的新冒险中,我在尝试从后端解析一些包含枚举值的数据时遇到了困难。
Spring-Boot 以 JSON 形式发送对象,如下所示:

{
  "id": 1,
  "username": "Johnny",
  "role": "CLIENT"
}

role在这种情况下是枚举值,可以有两个值CLIENTLECTURER。如果我要使用 java 库解析它或让 Spring-Boot 处理它,role将被解析为相应的枚举值。

使用 kotlin-js' JSON.parse,这是行不通的,我会在那里有一个简单的字符串值。

经过一些测试,我想出了这个片段

val json = """{
        "id": 1,
        "username": "Johnny",
        "role": "CLIENT",
    }"""

val member: Member = JSON.parse(json) { key: String, value: Any? ->
    if (key == "role") Member.Role.valueOf(value.toString())
    else value
}

在其中我必须手动定义从字符串值到枚举的转换。

有什么我遗漏的东西可以简化这种行为吗?

(我不是指为 JSON 使用 id 和查找这些,等等。我对 Kotlin-JS 中的一些方法很好奇)

我假设没有,因为JSON.parseJS 中的“原始”没有这样做,而且 Kotlin 没有在其中添加任何额外的东西,但我仍然有希望!

4

1 回答 1

4

据我所知,没有。

问题

Kotlin.JS 在使用嵌入的 JSON 类进行反序列化时会产生一种非常奇怪的类型情况,它实际上是JavaScript 的 JSON 类的镜像。虽然我没有做太多 JavaScript,但它的类型处理几乎不存在。只有手动抛出可以强制执行它,所以JSON.parse不关心它是否返回一个SomeCustomObject或新创建的具有完全相同字段的对象。

例如,如果您有两个具有相同字段名称(无继承)的不同类,并且有一个接受变量的函数,则它不关心它接收的那些(或第三个)中的哪一个只要它尝试在类上访问的变量存在。

类型问题体现在 Kotlin 中。现在将其包装回 Kotlin,考虑以下代码:

val json = """{
        "x": 1, "y": "yes", "z": {
            "x": 42, "y": 314159, "z": 444
        }
    }""".trimIndent()

data class SomeClass(val x: Int, val y: String, val z: Struct) 
data class Struct(val x: Int, val y: Int, val z: Int)

fun main(args: Array<String>) {
    val someInstance = JSON.parse<SomeClass>(json)
    if(someInstance.z::class != Struct::class) {
        println("Incompatible types: Required ${Struct::class}, found ${someInstance.z::class}");
    }
}

你希望这会打印什么?自然会期待一个Struct. 该类型也被显式声明

不幸的是,事实并非如此。相反,它打印:

Incompatible types: Required class Struct, found class Any

重点

嵌入式 JSON de/serializer 不适合类型。您也许可以通过使用不同的序列化库来解决此问题,但我会避免将其变成“使用 [this] 库”。

本质上,JSON.parse无法按预期解析对象。如果您完全删除参数并JSON.parse(json);在问题中尝试使用原始 JSON,您将得到 a rolethat is aString而不是 a Role,这可能是您所期望的。并且JSON.parse不进行任何类型转换,这意味着您有两个选择:使用库或使用您的方法。

不幸的是,如果您有嵌套对象,您的方法会变得复杂,但是随着类型的更改,您似乎留下的唯一选择是手动显式解析对象。

TL; DR:你的方法很好。

于 2019-03-23T22:09:26.223 回答