KotlinJS中如何将外部Node模块返回的JSON自动序列化为Kotlin类?
好问题!在KotlinJS里对接外部Node模块的API响应时,默认情况下不会自动把JS返回的JSON对象转换成你定义的@Serializable数据类,不过有两种实用的处理方式,根据你的需求来选:
方式一:直接映射JS对象(无需序列化)
如果外部API返回的字段结构和你的APIResponse完全匹配,最简单的方式是把APIResponse声明为external接口,让Kotlin直接将JS对象当作这个接口的实例来使用,完全不需要序列化步骤:
package ext.jspackage.someAPIClient // 用external interface直接映射JS对象的结构 external interface APIResponse { val data: List<DataInResponse> // KotlinJS会自动把JS数组转成List val start: Int val end: Int val timezone: String } // 同样给DataInResponse定义external接口 external interface DataInResponse { // 这里定义对应JS对象的字段,比如val id: String, val value: Int等 }
然后调整你的外部SomeAPIClient声明,让它返回这个APIResponse的Promise:
@file:JsModule("someapi-client") package ext.jspackage.someAPIClient import kotlin.js.Promise external class SomeAPIClient(apiKey: String) { fun getAPIResponse(someParam: String): Promise<APIResponse> }
这样调用的时候,你可以直接像操作Kotlin对象一样访问APIResponse的字段,KotlinJS会在底层帮你完成JS对象到Kotlin接口的绑定,非常省心。
方式二:用kotlinx-serialization手动转换
如果你需要用@Serializable数据类(比如要在多平台项目里复用,或者需要做其他序列化操作),那就要手动把JS对象转成JSON字符串,再反序列化为你的数据类:
首先确保你已经在项目里配置了kotlinx-serialization的依赖(在build.gradle.kts中):
plugins { kotlin("js") kotlin("plugin.serialization") version "你的Kotlin版本号" } dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:对应版本号") // 如果用协程的await(),还要加协程依赖 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-js:对应版本号") }
然后在调用API时做显式转换:
import kotlinx.serialization.json.Json import kotlin.js.JSON import ext.jspackage.someAPIClient.SomeAPIClient import kotlinx.coroutines.await suspend fun getParsedResponse(apiKey: String, param: String): APIResponse { val client = SomeAPIClient(apiKey) // 获取JS原生对象 val jsResponse = client.getAPIResponse(param).await() // 用JS原生的JSON.stringify把对象转成JSON字符串 val jsonStr = JSON.stringify(jsResponse) // 反序列化为你的@Serializable数据类 return Json.decodeFromString(jsonStr) }
如果不用协程,也可以用Promise的.then()链式调用:
fun getParsedResponse(apiKey: String, param: String, onSuccess: (APIResponse) -> Unit) { val client = SomeAPIClient(apiKey) client.getAPIResponse(param) .then { jsResponse -> val jsonStr = JSON.stringify(jsResponse) val parsed = Json.decodeFromString<APIResponse>(jsonStr) onSuccess(parsed) } }
为什么不能自动序列化?
简单来说,Kotlin的@Serializable注解是针对Kotlin自身的序列化体系,而外部Node模块返回的是JS原生对象,不属于这个体系管理的范围。Kotlin无法自动识别并转换JS对象到@Serializable数据类,必须通过显式映射或者手动序列化来完成转换。
内容的提问来源于stack exchange,提问作者bcosynot

