toJson 和 fromJson 跨平台支持

问题描述 投票:0回答:2

我有一个用 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 序列化和反序列化的帮助或建议将不胜感激。

android json kotlin kotlin-multiplatform
2个回答
8
投票

回答你的问题。你需要一个多平台 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(),"{}")

0
投票

有更简单的解决方案:)改编自 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
    )
}

© www.soinside.com 2019 - 2024. All rights reserved.