如何在带有枚举的kotlinjs中正确使用JSON.parse?

问题描述 投票:0回答:1

在我与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
}

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

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

(我不是指使用ID为JSON和查找它们等等。我很好奇Kotlin-JS中的某些方法)

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

json parsing kotlin enums kotlin-js
1个回答
5
投票

据我所知,没有。

The problem

使用嵌入式JSON类进行反序列化时,Kotlin.JS会产生一种非常奇怪的类型情况,实际上是一个mirror for JavaScript's JSON class。虽然我没有做太多的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上的原始JSON.parse(json);,那么您将获得role,它是String而不是Role,您可能会期望它。由于JSON.parse没有进行任何类型转换,这意味着您有两种选择:使用库或使用您的方法。

如果你有嵌套对象,你的方法将变得复杂,但是如果改变了类型,你看起来唯一的选择是手动显式解析对象。

TL; DR:你的方法很好。

© www.soinside.com 2019 - 2024. All rights reserved.