ktor 为某些数据抛出 类 一个 NoTransformationFoundException
ktor throws for some data classes an NoTransformationFoundException
我有一个功能分支,我在其中从休息服务加载数据。对于两个请求,这绝对按预期工作,但对于一个请求,我总是得到一个 NoTransformationFoundException。
我正在这样创建 http 客户端:
private val httpClient =
HttpClient(OkHttp) {
install(JsonFeature) {
serializer = GsonSerializer()
}
}
在上面你看到我正在使用带有 gson 的 okhttp。为了使问题更容易调试,这里是我的 ktor 依赖项:
compile "io.ktor:ktor-client-okhttp:1.2.6"
compile "io.ktor:ktor-client-json:1.2.6"
compile "io.ktor:ktor-client-gson:1.2.6"
像下面这样的请求对我来说没问题。 Here is the relevant documentation(包括响应 JSON):
data class Vendors(val vendors: List<Vendor>)
data class Vendor(
val id: String,
val name: String,
val roles: List<String>
)
fun fetchVendors() = runBlocking {
httpClient.get<Vendors>("https://api.amazonalexa.com/v1/vendors") {
headers.append("Authorization", "Bearer $accessToken")
}?.vendors
}
更新: 我知道一定有区别:上面的内容类型是 application/json
但是这个调用(获取技能,documentation here)总是失败:
data class Skills(
val isTruncated: Boolean,
val skills: List<Skill>
)
data class Skill(
val apis: List<String>,
val asin: String,
val lastUpdated: String,
val nameByLocale: Map<String, String>,
val publicationStatus: String,
val skillId: String,
val stage: String
)
fun fetchSkills(vendor: String) = runBlocking {
httpClient.get<Skills>("https://api.amazonalexa.com/v1/skills?vendorId=$vendor") {
headers.append("Authorization", "Bearer $accessToken")
}.skills
}
更新:这是响应内容类型:application/json+hal
我不明白为什么一个有效而另一个失败并出现此异常:
Exception in thread "main" io.ktor.client.call.NoTransformationFoundException: No transformation found: class kotlinx.coroutines.io.ByteBufferChannel -> class my.package.name.Skills
at io.ktor.client.call.HttpClientCall.receive(HttpClientCall.kt:88)
at my.package.name.AmazonApi$fetchSkills.invokeSuspend(AmazonApi.kt:200)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:215)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:172)
at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(PipelineContext.kt:122)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:215)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:172)
at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(PipelineContext.kt:122)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:215)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:172)
at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(PipelineContext.kt:122)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:270)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at my.package.name.AmazonApi.fetchSkills(AmazonApi.kt:131)
at my.package.name.Cli.createProject(Cli.kt:305)
at my.package.name.Cli.parseArgs(Cli.kt:208)
at my.package.name.Cli$Companion.main(Cli.kt:508)
at my.package.name.Cli.main(Cli.kt)
请给我一些解决此问题的提示,或者至少给我一些调试方法。顺便说一句,当我使用 String 而不是 Skill 时,我看到了预期的响应 JSON.
根据 GitHub 评论,我能够使用此解决方法:
val httpClient = HttpClient(OkHttp) {
install(JsonFeature) {
serializer = GsonSerializer()
acceptContentTypes += ContentType("application", "json+hal")
}
}
但是我仍在寻找更好的解决方案而不引起警告。
一般使用
implementation("io.ktor", "ktor-client-core", ktorVersion)
implementation("io.ktor", "ktor-client-serialization", ktorVersion)
然后像这样配置客户端:
HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer()
// accept(ContentType.Application.Json)
}
}
将自动选择正确的引擎。当然你可以使用其他序列化器(比如 reikire 的回答中的 Gson)。
我有一个功能分支,我在其中从休息服务加载数据。对于两个请求,这绝对按预期工作,但对于一个请求,我总是得到一个 NoTransformationFoundException。
我正在这样创建 http 客户端:
private val httpClient =
HttpClient(OkHttp) {
install(JsonFeature) {
serializer = GsonSerializer()
}
}
在上面你看到我正在使用带有 gson 的 okhttp。为了使问题更容易调试,这里是我的 ktor 依赖项:
compile "io.ktor:ktor-client-okhttp:1.2.6"
compile "io.ktor:ktor-client-json:1.2.6"
compile "io.ktor:ktor-client-gson:1.2.6"
像下面这样的请求对我来说没问题。 Here is the relevant documentation(包括响应 JSON):
data class Vendors(val vendors: List<Vendor>)
data class Vendor(
val id: String,
val name: String,
val roles: List<String>
)
fun fetchVendors() = runBlocking {
httpClient.get<Vendors>("https://api.amazonalexa.com/v1/vendors") {
headers.append("Authorization", "Bearer $accessToken")
}?.vendors
}
更新: 我知道一定有区别:上面的内容类型是 application/json
但是这个调用(获取技能,documentation here)总是失败:
data class Skills(
val isTruncated: Boolean,
val skills: List<Skill>
)
data class Skill(
val apis: List<String>,
val asin: String,
val lastUpdated: String,
val nameByLocale: Map<String, String>,
val publicationStatus: String,
val skillId: String,
val stage: String
)
fun fetchSkills(vendor: String) = runBlocking {
httpClient.get<Skills>("https://api.amazonalexa.com/v1/skills?vendorId=$vendor") {
headers.append("Authorization", "Bearer $accessToken")
}.skills
}
更新:这是响应内容类型:application/json+hal
我不明白为什么一个有效而另一个失败并出现此异常:
Exception in thread "main" io.ktor.client.call.NoTransformationFoundException: No transformation found: class kotlinx.coroutines.io.ByteBufferChannel -> class my.package.name.Skills
at io.ktor.client.call.HttpClientCall.receive(HttpClientCall.kt:88)
at my.package.name.AmazonApi$fetchSkills.invokeSuspend(AmazonApi.kt:200)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:215)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:172)
at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(PipelineContext.kt:122)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:215)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:172)
at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(PipelineContext.kt:122)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith(PipelineContext.kt:215)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(PipelineContext.kt:172)
at io.ktor.util.pipeline.SuspendFunctionGun.access$loop(PipelineContext.kt:67)
at io.ktor.util.pipeline.SuspendFunctionGun$continuation.resumeWith(PipelineContext.kt:122)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:270)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at my.package.name.AmazonApi.fetchSkills(AmazonApi.kt:131)
at my.package.name.Cli.createProject(Cli.kt:305)
at my.package.name.Cli.parseArgs(Cli.kt:208)
at my.package.name.Cli$Companion.main(Cli.kt:508)
at my.package.name.Cli.main(Cli.kt)
请给我一些解决此问题的提示,或者至少给我一些调试方法。顺便说一句,当我使用 String 而不是 Skill 时,我看到了预期的响应 JSON.
根据 GitHub 评论,我能够使用此解决方法:
val httpClient = HttpClient(OkHttp) {
install(JsonFeature) {
serializer = GsonSerializer()
acceptContentTypes += ContentType("application", "json+hal")
}
}
但是我仍在寻找更好的解决方案而不引起警告。
一般使用
implementation("io.ktor", "ktor-client-core", ktorVersion)
implementation("io.ktor", "ktor-client-serialization", ktorVersion)
然后像这样配置客户端:
HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer()
// accept(ContentType.Application.Json)
}
}
将自动选择正确的引擎。当然你可以使用其他序列化器(比如 reikire 的回答中的 Gson)。