使用Ktor KotlinxSerializationConverter转换JSON至UserInfo时遇转换异常
排查Ktor序列化转换报错:No suitable converter found for TypeInfo
核心排查方向
1. 确认转换器注册顺序与优先级
自定义的AgentBodyConvertor如果在KotlinxSerializationConverter之前注册,可能会拦截请求但无法处理目标类型,导致找不到合适转换器。确保注册顺序是先官方序列化转换器,再自定义空响应转换器:
install(ContentNegotiation) { json(yourJsonConfig) // 先注册KotlinxSerializationConverter register(ContentType.Application.Json, AgentBodyConvertor()) // 再注册自定义转换器 }
2. 检查TypeInfo匹配与泛型处理
报错提示找不到对应TypeInfo,大概率是泛型解析问题。如果接口返回的是AgentBaseResponse<AgentBaseRespData<UserInfo>>这类嵌套泛型,要确保调用receive时明确指定完整泛型类型,避免类型擦除:
val response = client.get("/user/info").receive<AgentBaseResponse<AgentBaseRespData<UserInfo>>>() val userInfo = response.data?.data
不要省略泛型参数,也不要用Any或模糊类型接收后强转。
3. 验证Json配置的序列化规则
确保Json配置开启必要选项,同时检查序列化类的注解与字段匹配:
val yourJsonConfig = Json { ignoreUnknownKeys = true // 避免服务器返回额外字段导致解析失败 coerceInputValues = true // 自动处理空值或类型不匹配的字段 explicitNulls = false // 可根据服务器返回调整 }
确认AgentBaseResponse、AgentBaseRespData、UserInfo类都添加了@Serializable注解,内部字段的序列化名称和服务器返回的JSON键完全匹配(大小写、下划线/驼峰不一致时用@SerialName指定)。
4. 自定义转换器的逻辑边界
AgentBodyConvertor仅处理空响应场景,不要覆盖正常JSON响应的处理逻辑。示例逻辑参考:
class AgentBodyConvertor : ContentConverter { override suspend fun convertForReceive(context: PipelineContext<ApplicationReceiveRequest, ApplicationCall>): Any? { val request = context.subject val contentType = request.contentType() ?: return null if (contentType.match(ContentType.Application.Json)) { val content = request.value as ByteReadChannel if (content.isClosedForRead) { // 处理空响应,返回对应空结构 return AgentBaseResponse<AgentBaseRespData<UserInfo>>(code = 200, message = "success", data = null) } // 非空响应交给后续官方转换器处理 return null } return null } override suspend fun convertForSend(context: PipelineContext<Any, ApplicationCall>, contentType: ContentType): Any? { return null // 发送逻辑交给官方转换器 } }
如果自定义转换器错误处理了非空响应,会导致官方转换器无法接手,触发找不到转换器的报错。
5. 检查服务器响应的ContentType
确保服务器返回的Content-Type头是application/json,如果是text/plain等其他类型,需手动指定接收时的ContentType:
val response = client.get("/user/info") { accept(ContentType.Application.Json) }.receive<AgentBaseResponse<AgentBaseRespData<UserInfo>>>()
或者在ContentNegotiation中注册对应ContentType的转换器。
内容的提问来源于stack exchange,提问作者sleeper
相关产品推荐
相关产品推荐

