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

时间:2019-03-23 18:02:38

标签: json parsing kotlin enums kotlin-js

在使用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并查找ID,等等。我对Kotlin-JS中的某些方法感到好奇)

我有一个假设,那就是因为JS中的“原始” JSON.parse不能做到这一点,而且Kotlin不会在其中添加任何其他内容,但是我还是有希望的!

1 个答案:

答案 0 :(得分:5)

据我所知,没有。

问题

在使用嵌入式JSON类反序列化时,Kotlin.JS产生了一种非常奇怪的类型情况,该类实际上是mirror for JavaScript's JSON class。尽管我还没有做很多JavaScript,但是它的类型处理几乎不存在。只有手动抛出才能执行它,因此SomeCustomObject不在乎是否返回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}"); } } 或具有完全相同字段的新创建对象。

例如,如果您有两个具有相同字段名的类(没有继承),并且有一个接受变量的函数,那么它不在乎其中的哪一个(或第三个)只要它尝试访问该类的变量存在,它就会接收。

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

Struct

您希望此打印什么?很自然地会期望一个Incompatible types: Required class Struct, found class Any 。该类型也已明确声明

不幸的是,事实并非如此。而是打印:

JSON.parse

要点

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

本质上,JSON.parse(json);无法按预期解析对象。如果您完全删除参数并在问题中的JSON上尝试使用原始的role,则会得到String而不是Role的{​​{1}},您可能会期望。而JSON.parse从来没有进行类型转换,这意味着您有两个选择:使用库或使用方法。

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

TL; DR:您的方法很好。