在使用Kotlin-react进行新的冒险期间,尝试解析后端中包含枚举值的某些数据时,我遇到了困难。
Spring-Boot以JSON形式发送对象,如下所示:
{
"id": 1,
"username": "Johnny",
"role": "CLIENT"
}
role
在此是枚举值,可以具有两个值CLIENT
和LECTURER
。如果我要使用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不会在其中添加任何其他内容,但是我还是有希望的!
答案 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:您的方法很好。