Ktor拦截器调用response.bodyAsText致响应体无法反序列化问题
问题解决:Ktor记录响应体后反序列化失败
核心原因
Ktor的响应体是一次性消费的字节流,调用response.bodyAsText()会将流中的数据全部读取完毕,后续再尝试反序列化时,流已经处于EOF(文件末尾)状态,因此抛出JsonDecodingException错误。
解决方案1:使用拦截器时复制响应体流
在HttpSend拦截器中,不要直接调用bodyAsText(),而是通过复制响应体的流来读取内容,保留原始流供后续反序列化使用:
val client = HttpClient { install(ContentNegotiation) { json(json) } install(Logging) { logger = Logger.DEFAULT level = LogLevel.ALL } defaultRequest { url(BuildConfig.HOST_NAME) contentType(ContentType.Application.Json) accept(ContentType.Application.Json) } }.apply { plugin(HttpSend).intercept { req -> val call = execute(req) val response = call.response // 复制响应体流,读取副本内容 val responseBody = response.content.copy().readText() println("responseBody=$responseBody") call } }
解决方案2:修复Logging插件使其生效
你安装的Logging插件未生效,大概率是默认Logger的输出未被正确捕获(比如Android环境下默认Logger可能不输出到Logcat)。可以自定义Logger实现,确保日志能正常输出:
install(Logging) { logger = object : Logger { override fun log(message: String) { // 替换成你项目中的日志工具,比如Android的Log println("Ktor Client Log: $message") // 如果是Android:Log.d("KtorClient", message) } } level = LogLevel.ALL }
配置后,Logging插件会自动记录请求/响应的详细信息,包括响应体,无需手动写拦截器。
关于response.body<Any>()无效的说明
body<Any>()无法解析JSON内容是因为Any没有对应的序列化规则,Ktor不会尝试解析响应体,直接返回HttpResponse对象的字符串表示,因此输出没有实际价值。
内容的提问来源于stack exchange,提问作者MikkelT
相关产品推荐
相关产品推荐

