我有一个用 Kotlin 编写的 Android 应用程序。我有很多类,对于每个类,我都使用
Gson's
toJson
和 fromJson
函数。例如:
class A{
fun toJson():String {
return Gson().toJson(this)
}
fun fromJson(jsonString:String):A{
return Gson().fromJson(jsonString, A::class)
}
}
我还有课
B
:
class B{
fun toJson():String {
return Gson().toJson(this)
}
fun fromJson(jsonString:String):B{
return Gson().fromJson(jsonString, B::class)
}
}
我使用它的方式是创建该类的实例,然后调用该方法(注意:我正在另一个类中创建该类的实例(
class A
):
val a = A()
a.toJson()
但我现在正在尝试将其转换为 kotlin 多平台项目,但不确定如何在 kotlin 多平台中进行
to
和 from
json 转换。
我尝试创建这样的期望函数:
expect fun toJsonClassA():String
expect fun fromJsonClassA(jsonString: String): A
class A{
}
然后实现它们的实际实现如下:
actual fun toJsonClassA(): String {
return Gson().toJson(A::class.java)
}
通过上述平台特定的实现,我无法使用类名的实例调用
toJsonClassA
或 fromJsonClassA
函数。
这行不通:
val a = A()
a.toJsonClassA()
任何关于如何在 Kotlin Multiplatform 中实现 Json 序列化和反序列化的帮助或建议将不胜感激。
回答你的问题。你需要一个多平台 json 序列化器(不是 GSon,因为它仅适用于 jvm),目前我只知道
kotlinx.serialization
。有了它,你的代码应该看起来像这样
@Serializable
class A {
fun toJson() = Json.stringify(A.serializer(),this)
companion object {
fun fromJson(json: String) = Json.parse(A.serializer(),json)
}
}
虽然这可行,但您不需要
toJson
和 fromJson
方法。从你有这样的课程开始
@Serializable
class B {}
val b = B()
您需要的一切,
kotlinx.serialization
Json
, Json.stringify(B.serializer(),b)
Json
解析为 kotlin 对象,Json.parse(B.serializer(),"{}")
有更简单的解决方案:)改编自 connect-http-client
import co.touchlab.kermit.Logger
import dev.gitlive.firebase.Firebase
import dev.gitlive.firebase.storage.storage
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.get
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
/**
* adapted from [connect-http-client](https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-upgrade-app.html#connect-http-client)
*/
class JsonToObjectTest {
private val dispatcherScope = CoroutineScope(Dispatchers.Default)
private val firebaseStorage = Firebase.storage
private val httpClient = HttpClient {
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
})
}
}
init {
dispatcherScope.launch {
testDataJsonToObject()
convertTestDataObjectToJson()
}
}
// this example fetches json file stored in firebase storage and converts it to `TestData` object
private suspend fun testDataJsonToObject(): TestData? {
return try {
val jsonFile = firebaseStorage.reference("/TestData.json")
// get the url for the json file
val url = jsonFile.getDownloadUrl()
// convert the json file into TestData
httpClient.get(url).body<TestData>()
} catch (e: Exception) {
Logger.e("getTestData error", e)
null
}
}
// convert object to json string
private fun convertTestDataObjectToJson() {
val testData = TestData(
name = "puppy lucy",
icon = ":)"
)
val json = Json.encodeToString(testData)
println("++testData json: $json")
}
@Serializable
data class TestData(
val name: String,
val icon: String
)
}