Kotlinx.Serialization 使用 OkHTTPClient return 总是失败

Kotlinx.Serialization using OkHTTPClient return always Failure

您好,我的 JSON 有问题。我正在使用 OkHTTPClient 从 Web 获取 JSON - 使用包含此方法的 kotlinx.serialization 从 JSON 获取对象,方法的 return 值应该是结果:

private suspend inline fun <reified T> OkHttpClient.get(webUrl: HttpUrl): Result<T> =
    try {
        //Builder defined here ... but skipping this line of code
        val data = Json { ignoreUnknownKeys = true }.decodeFromString<T (result.body!!.string())
        Result.Success(data)
    } catch (e: Exception) {
        Result.Failure(e)
    }


 suspend fun getFact(): Result<Fact> =
        client.httpGet("myURL".toHttpUrl())

Json 来自我的网址:

{"status":"success","data":[{"fact":"This is random information i need to get"}],"message":"Retrieved Fact"} 

我的序列化器和序列化数据类:


@Serializable
data class Fact(
@Serializable(with = FactListSerializer::class)
val data: String) java.io.Serializable

object FactListSerializer : JsonTransformingSerializer<List<String>>(ListSerializer(String.serializer())) {
    override fun transformDeserialize(element: JsonElement): JsonElement {
        return if (element  is JsonArray) {
            JsonArray(listOf(element)).first()
        } else {
            element
        }
    }
}

老实说,我不确定自己在做什么,但是当我打印 val fact = api.getFact():

时,我总是遇到这个错误
 Fact: Failure(error=kotlinx.serialization.json.internal.JsonDecodingException: Expected JsonPrimitive at 0, found {"fact":"This is random information i need to get"}

我需要return只是数组事实的第一个元素,因为JSON总是只获得数组中的一个事实。所以我不想从 Serializer/Json 列表中 return 而只是 Fact 对象。 但是正如您所见,我总是获得结果失败,不知道为什么。我的目] 来自 JSON仅排列一个对象(事实类型的元素)。

所以我期望的是这样的:

Fact: Success(value=Fact(fact=This is random information i need to get))

我认为解串器定义应该在 3 个级别上进行更改。如何使用 JsonTransformingDeserializer in the docs 的示例实际上描述了您需要的大部分内容。

  1. JsonArray(listOf(element)).first() 应该只是 element.first()。在这里你正在构建一个 JsonArray 包含你的初始 JsonArray 作为唯一元素,然后取第一个,所以你基本上得到完全相同的元素。

  2. JsonTransformingSerializer 的类型参数 T 应该是它所应用的 属性 的类型,所以你至少应该得到一个警告代码,因为您的代码被定义为适用于 List<String>,但适用于 String 属性。应该是 JsonTransformingSerializer<String>(String.serializer()).

  3. 您不仅需要解包 data 数组,还需要提取该数组元素中 fact 键的值。

所以有了所有这些变化,它应该给出这样的东西:

object FactListSerializer : JsonTransformingSerializer<String>(String.serializer()) {
    override fun transformDeserialize(element: JsonElement): JsonElement {
        val unwrappedData = if (element is JsonArray) element.first() else element
        return unwrappedData.jsonObject["fact"] ?: error("missing 'fact' key in 'data' array")
    }
}