Ano*_*age 6 serialization json kotlin
我正在学习如何使用 Ktor 的 HttpClient。而且,我希望它能够自动将 JSON 响应转换为数据类。我认为我的所有设置都是正确的(粘贴在下面),但不幸的是,java.time.Instant使用了import java.io.Serializable;,我猜它与 kotlinx 的 不兼容@kotlinx.serialization.Serializable。
那么,如何让 Ktor 识别Instant为可序列化呢?
val httpClient = HttpClient(CIO) {
install(JsonFeature) {
serializer = KotlinxSerializer(Json {
prettyPrint = true
isLenient = true
})
}
}
val response: MyResponse = httpClient.get(baseUrl() + "/example/path") {
contentType(ContentType.Application.Json)
}
@kotlinx.serialization.Serializable
data class MyResponse(
val name: String,
val time: Instant // ERROR: "Serializer has not been found for type 'Instant'. To use context serializer as fallback, explicitly annotate type or property with @Contextual"
)
Run Code Online (Sandbox Code Playgroud)
旁注:使用 Gson 或 Jackson 或其他序列化器的其他答案也可能很有用,因为它们可能不必显式添加@Serializable
Sla*_*law 11
如果您想要或需要继续java.time直接使用,另一个解决方案是为java.time.Instant. 请参阅以下示例。注意使用 Kotlin 1.9.0、Kotlin Serialization 1.5.1 和 Gradle 8.2.1 进行测试。
InstantSerializer.kt:
package sample
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.time.Instant
object InstantSerializer : KSerializer<Instant> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("java.time.Instant", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Instant) = encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): Instant = Instant.parse(decoder.decodeString())
}
Run Code Online (Sandbox Code Playgroud)
Note: Encoding to, and decoding from, the ISO-8601 representation ensures no precision is lost. That's one of the approaches used by the kotlinx-datetime library (see here). The other approach that library offers is to encode the epoch seconds and nano-of-seconds separately, both as numbers. If you prefer that, look at the library's implementation (linked earlier). Also note that when running on the JVM, the kotlinx-datetime classes are backed by the java.time classes.
Event.kt (the serializable data class with an Instant property):
@file:UseSerializers(InstantSerializer::class)
package sample
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
import java.time.Instant
@Serializable
data class Event(val name: String, val instant: Instant)
Run Code Online (Sandbox Code Playgroud)
Note: An alternative to using to using @UseSerializers would be to annotate the instant property with @Serializable(InstantSerializer::class).
Main.kt:
package sample
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.time.Instant
fun main() {
val event = Event("Test Event", Instant.now())
val jsonString = Json.encodeToString(event)
val decodedEvent = Json.decodeFromString<Event>(jsonString)
println("Original Event = $event")
println("JSON String = $jsonString")
println("Decoded Event = $decodedEvent")
}
Run Code Online (Sandbox Code Playgroud)
Example output:
Original Event = Event(name=Test Event, instant=2023-07-11T10:16:34.742769200Z)
JSON String = {"name":"Test Event","instant":"2023-07-11T10:16:34.742769200Z"}
Decoded Event = Event(name=Test Event, instant=2023-07-11T10:16:34.742769200Z)
Run Code Online (Sandbox Code Playgroud)
Here was the Gradle build file used to run the above code (Kotlin DSL):
plugins {
kotlin("jvm") version "1.9.0"
kotlin("plugin.serialization") version "1.9.0"
application
}
application {
mainClass.set("sample.MainKt")
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
}
Run Code Online (Sandbox Code Playgroud)
And it was executed with:
./gradlew run
Run Code Online (Sandbox Code Playgroud)
Ano*_*age 10
一种解决方案是使用 kotlinx-datetime 库(https://github.com/Kotlin/kotlinx-datetime@kotlinx.serialization.Serializable ),它为您提供了具有您正在寻找的功能的 Kotlin 版本的 Instant 。
因此,java.time.Instant您可以kotlinx.datetime.Instant在 MyResponse 中使用,而不是使用 。
请注意,该库是实验性的,API 可能会发生变化。(来源:https ://github.com/Kotlin/kotlinx-datetime#using-in-your-projects )
| 归档时间: |
|
| 查看次数: |
7829 次 |
| 最近记录: |