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 的示例实际上描述了您需要的大部分内容。
JsonArray(listOf(element)).first()
应该只是 element.first()
。在这里你正在构建一个 JsonArray
包含你的初始 JsonArray
作为唯一元素,然后取第一个,所以你基本上得到完全相同的元素。
JsonTransformingSerializer
的类型参数 T
应该是它所应用的 属性 的类型,所以你至少应该得到一个警告代码,因为您的代码被定义为适用于 List<String>
,但适用于 String
属性。应该是 JsonTransformingSerializer<String>(String.serializer())
.
您不仅需要解包 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")
}
}
您好,我的 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 的示例实际上描述了您需要的大部分内容。
JsonArray(listOf(element)).first()
应该只是element.first()
。在这里你正在构建一个JsonArray
包含你的初始JsonArray
作为唯一元素,然后取第一个,所以你基本上得到完全相同的元素。JsonTransformingSerializer
的类型参数T
应该是它所应用的 属性 的类型,所以你至少应该得到一个警告代码,因为您的代码被定义为适用于List<String>
,但适用于String
属性。应该是JsonTransformingSerializer<String>(String.serializer())
.您不仅需要解包
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")
}
}