我正在研究当前 Android 项目中的 ktor 客户端以使用 websocket 流。
我的 ktor 客户端配置如下:-
val client = HttpClient(OkHttp) {
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = false
isLenient = true
encodeDefaults = true
coerceInputValues = true
explicitNulls = false
})
}
install(WebSockets) {
pingInterval = 20_000
}
}
我的 websocket 会话配置如下:-
client.webSocket(urlString = "wss://stream.org") {
incoming.consumeEach { frame ->
when (frame) {
is Frame.Binary -> println("Frame.Binary = $frame")
is Frame.Text -> {
println("Frame.Text = $frame")
val incoming = frame.readText()
println("\tincoming $incoming")
val eventResponse = json.decodeFromString<WebSocketResponse>(incoming)
when (eventResponse.event) {
Event.CONNECTED -> println("Event.SUBSCRIPTION_CREATED = $incoming")
Event.SUBSCRIPTION_CREATED -> println("Event.SUBSCRIPTION_CREATED = $incoming")
Event.SUBSCRIPTION_DELETED -> println("Event.SUBSCRIPTION_DELETED = $incoming")
Event.TOPIC_ADDED -> println("Event.TOPIC_ADDED = $incoming")
Event.TOPIC_REMOVED -> println("Event.TOPIC_REMOVED = $incoming")
Event.TOPIC_UPDATED -> println("Event.TOPIC_UPDATED = $incoming")
else -> TODO("Unexpected event $eventResponse")
}
}
is Frame.Close -> println("Frame.Close = $frame")
is Frame.Ping -> println("Frame.Ping = $frame")
is Frame.Pong -> println("Frame.Pong = $frame")
else -> TODO("Unexpected frame = $frame")
}
}
}
json
中的val eventResponse = json.decodeFromString<WebSocketResponse>(incoming)
是一个与 ktor 客户端中配置的不同的 json 实例,因为我已经声明它用于通过改造处理 Restful api 调用
其声明如下:-
@OptIn(ExperimentalSerializationApi::class)
val json = Json {
ignoreUnknownKeys = true
isLenient = true
encodeDefaults = true
coerceInputValues = false
explicitNulls = false
}
如何使用我为内容协商配置的 json 实例?
您无法从
Json
插件访问 ContentNegotiation
实例,但您可以使用预定义的 Json
对象配置插件并将其用于 WebSockets 数据包反序列化。
@OptIn(ExperimentalSerializationApi::class)
val jsonInstance = Json {
ignoreUnknownKeys = true
isLenient = true
encodeDefaults = true
coerceInputValues = false
explicitNulls = false
}
val client = HttpClient {
install(ContentNegotiation) {
json(jsonInstance)
}
}
// ...
// Usage of jsonInstance for WebSockets packet deserialization