您好,我在 kotlin 中类序列化时遇到问题
构建.gradl.kt
...
plugins {
application
kotlin("jvm") version "1.6.21"
kotlin("plugin.serialization").version("1.6.21")
}
...
depenedancies{
...
implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
}
Run Code Online (Sandbox Code Playgroud)
响应.kt
import kotlinx.serialization.*
...
interface BaseResponse<T>
@Serializable
data class PaginatedResponse<T>(
val prev: Int?,
val next: Int?,
val totalCount: Int = 0,
val totalPages: Int = 0,
val data: T? = null,
val message: String? = null
) : BaseResponse<T>
Run Code Online (Sandbox Code Playgroud)
用法
...
return PaginatedResponse<List<User>>(
prev,
next,
totalCount,
totalPages,
users
)
Run Code Online (Sandbox Code Playgroud)
kotlinx.serialization.SerializationException: Serializer for class 'PaginatedResponse' is not found.
Mark the …Run Code Online (Sandbox Code Playgroud) 我在公共模块中编写了如下公共代码,并在JS环境中进行了测试
val response = client.post<HttpResponse>(url) {
body = TextContent("""{"a":1,"b":2}""", ContentType.Application.Json)
}
if (response.status != HttpStatusCode.OK) {
logger.error("Error, this one failed bad?")
}
Run Code Online (Sandbox Code Playgroud)
但我的代码以 client.post 结尾,在没有网络的情况下出现取消的 corutineException 。我该如何处理这个异常以及任何其他异常?如果有互联网连接。没有任何失败,我希望能够处理异常。如何?
注意:try、catch 不起作用
当我运行我的 Ktor 应用程序时,gradle run我遇到了以下异常:
19:21:11.795 [main] DEBUG io.netty.util.internal.logging.InternalLoggerFactory - Using SLF4J as the default logging framework
19:21:11.810 [main] DEBUG io.netty.util.internal.PlatformDependent0 - -Dio.netty.noUnsafe: false
19:21:11.810 [main] DEBUG io.netty.util.internal.PlatformDependent0 - Java version: 11
19:21:11.811 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
19:21:11.812 [main] DEBUG io.netty.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
19:21:11.812 [main] DEBUG io.netty.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
19:21:11.814 [main] DEBUG io.netty.util.internal.PlatformDependent0 - direct buffer constructor: unavailable
java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled
at io.netty.util.internal.ReflectionUtil.trySetAccessible(ReflectionUtil.java:31)
at io.netty.util.internal.PlatformDependent0$4.run(PlatformDependent0.java:225)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:219)
at io.netty.util.internal.PlatformDependent.isAndroid(PlatformDependent.java:273)
at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:92) …Run Code Online (Sandbox Code Playgroud) 更新:如果我首先在没有超时的情况下执行协程然后使用超时,它会起作用。但是如果我先执行一个协程 withTimeout 那么它会给我一个错误。异步也是如此。
我正在创建一个演示 kotlin 多平台应用程序,我在其中使用 ktor 执行 API 调用。我想在 ktor 请求上有一个可配置的超时函数,所以我在协程级别使用 withTimeout 。
这是我使用网络 API 调用的函数。
suspend fun <T> onNetworkWithTimeOut(
url: String,
timeoutInMillis: Long,
block: suspend CoroutineScope.() -> Any): T {
return withTimeout(timeoutInMillis) {
withContext(dispatchers.io, block)
} as T
}
suspend fun <T> onNetworkWithoutTimeOut(url: String, block: suspend CoroutineScope.() -> Any): T {
return withContext(dispatchers.io, block) as T
}
Run Code Online (Sandbox Code Playgroud)
这是我的 iOSMain 模块的 AppDispatcher 类。
@InternalCoroutinesApi
actual class AppDispatchersImpl : AppDispatchers {
@SharedImmutable
override val main: CoroutineDispatcher =
NsQueueDispatcher(dispatch_get_main_queue())
@SharedImmutable
override …Run Code Online (Sandbox Code Playgroud) 我正在尝试获取并反序列化github上托管的一些数据。
{
"Meals": [
{
"id": "1598044e-5259-11e9-8647-d663bd870b02",
"name": "Tomato pasta",
"quantity": [{
"quantity": 1 },
{
"quantity": 2
},
{
"quantity": 3
}],
"availableFromDate": "1605802429",
"expiryDate": "1905802429",
"info": "Vegetarian",
"hot": false,
"locationLat": 57.508865,
"locationLong": -6.292,
"distance": null
},
{
"id": "2be2d854-a067-43ec-a488-2e69f0f2a624",
"name": "Pizza",
"quantity": [{
"quantity": 1 },
{
"quantity": 2
},
{
"quantity": 3
}
],
"availableFromDate": "1605802429",
"expiryDate": "1905902429",
"info": "Meat",
"hot": false,
"locationLat": 51.509465,
"locationLong": -0.135392,
"distance": null
}
]
}
Run Code Online (Sandbox Code Playgroud)
如果我在本地启动json 服务器,那么它会完美工作,所以我知道我的数据类不是问题。但是,当我尝试从 github …
在我的移动应用程序中,我有一个单例 Ktor HttpClient,其不记名身份验证配置如下:
HttpClient(\xe2\x80\xa6) {\n install(Auth) {\n bearer {\n sendWithoutRequest { requestBuilder -> some condition }\n loadTokens(tokensStorage::getTokens)\n refreshTokens {\n performTokenRefresh(oldTokens.refreshToken)\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n现在考虑以下流程:
\ntokenStorage无效。HttpClient令牌tokenStorage,请求失败并返回 401。HttpClient执行刷新,但也失败,因为刷新令牌无效。tokenStorage.HttpClient不再尝试调用loadTokens。确实,从源代码来看,loadTokens只被调用一次,然后就不会再被调用。我找到了解决该问题的几种方法。
\n第一个是手动BearerAuthProvider从HttpClient自己清除令牌,如以下代码片段所示,但这似乎是一种黑客解决方法:
httpClient.plugin(Auth).providers\n .filterIsInstance<BearerAuthProvider>()\n .first().clearToken()\nRun Code Online (Sandbox Code Playgroud)\ntokenStorage另一种方法是从 my in手动加载当前令牌refreshToken并忽略传入的内容this@refreshTokens.oldTokens …
我正在 android 中启动基于 Ktor 的客户端,我想使用任何序列化器,目前是来自 kotlinx 的序列化器,但结果与其他序列化器相同 - 未找到 JsonFeature(在下面的代码片段中突出显示)。我缺少什么?
class StreamClient {
val client: HttpClient
init {
client = HttpClient(Android) {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
摇篮:
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-android:$ktor_version")
implementation("io.ktor:ktor-client-serialization:$ktor_version")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0")
Run Code Online (Sandbox Code Playgroud) 我正在使用 Ktor 从 Moshi 转换为 kotlinx 序列化,当我尝试请求获取数据时,我收到此错误
kotlinx.serialization.MissingFieldException: 字段 'attachments' 是必需的,但它丢失了
这是有道理的,因为此特定响应不包含此字段
响应JSON
{
"data": {
"id": "1299418846990921728",
"text": "This is a test"
}
}
Run Code Online (Sandbox Code Playgroud)
但是我的 Serialized 类将该attachments字段设为可空(它仅在需要时才在响应中)所以它应该忽略它我想就像它对 Moshi 所做的那样
@Serializable
data class ResponseData(
val id: Long
val attachments: Attachments?,
val author_id: String?,
val text: String
}
Run Code Online (Sandbox Code Playgroud)
在我的 Ktor 客户端设置中,我将其设置为忽略未知密钥
private val _client: HttpClient = HttpClient(engine) {
install(JsonFeature) {
val json = Json {
this.isLenient = true
this.ignoreUnknownKeys = true
}
serializer = KotlinxSerializer(json)
}
}
Run Code Online (Sandbox Code Playgroud)
为什么它仍然说该字段是必需的,即使它可以为空?
尝试在IntelliJ中构建Kotlin / Ktor应用程序时,出现以下形式的多个警告
Warning:(276, 6) Kotlin: This class can only be used with the compiler argument '-Xuse-experimental=kotlin.Experimental'
Run Code Online (Sandbox Code Playgroud)
输出。警告是指
@UseExperimental(KtorExperimentalLocationsAPI::class)
Run Code Online (Sandbox Code Playgroud)
所以预期通过设定以满足警告设置- >构建- >编译器- >科特林编译器- >附加的命令行参数来-version -Xuse-实验= kotlin.Experimental。(-version已经在那里)。但是仍会生成警告。我如何满足呢?谢谢您的期待。
当尝试从 openapi 为 ktor 生成服务器端存根时,对我来说输出看起来并不是很实用。
我在 Github 上设置了一个示例项目,可以在其中查看设置。因为我需要在我的实际项目中使用 maven,所以我在这里也使用了它,但我想这对其他生成方法应该没有影响。
POM 的相关部分是这样的:
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>resources</id>
<phase>compile</phase>
<goals><goal>copy-resources</goal></goals>
<configuration>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Run Code Online (Sandbox Code Playgroud)
将生成的内容如下:
Paths.kt包含 ktor-locations 格式的路径路径的对象io.ktor.routing.Route来自 SpringBoot 和 Swagger,我有点困惑,因为如果您想创建一个实现真正业务逻辑的实际应用程序,这组文件并不是很有用。我本来希望一些默认实现包含我只需要实现/覆盖的单个方法。我意识到 ktor 没有内置 DI,所以我也希望必须以routing某种方式扩展我的应用程序中的存根。
但是,有了这组生成的代码,我真的只能使用数据模型和Paths.kt对象。我将拥有自己的应用程序和默认实现,我无法覆盖但需要自己完全重写。
所以我的问题是,如何设置一个合适的 ktor 应用程序实现 openapi 规范。我是否错过了什么,或者我真的只得到模型并Paths.kt与之合作?
编辑
为了更清楚:特别是对于我的应用程序的这些部分,我不高兴没有工具的支持:
fun Application.module(testing: Boolean = false) { …Run Code Online (Sandbox Code Playgroud)