在我与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
}
我手动必须定义从字符串值到枚举的转换。
有什么我想念的东西可以简化这种行为吗?
(我不是指使用ID为JSON和查找它们等等。我很好奇Kotlin-JS中的某些方法)
我假设没有,因为JS中的“原始”JSON.parse
没有这样做,Kotlin没有添加任何额外的东西,但我仍然有希望!
据我所知,没有。
使用嵌入式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:你的方法很好。