如何使用ktor ContentNegotiation为websocket客户端进行json反序列化

问题描述 投票:0回答:1

我正在研究当前 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 ktor ktor-client
1个回答
0
投票

您无法从

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 
© www.soinside.com 2019 - 2024. All rights reserved.