Ktor序列化遇JsonConvertException:API字段变更致解析失败求助
解决Ktor客户端因服务端字段频繁变名导致的JsonConvertException问题
服务端API处于开发阶段时,字段命名(驼峰/下划线来回切换)很容易导致Ktor的Kotlinx Serialization抛出io.ktor.serialization.JsonConvertException: Invalid input异常,每次都要修改@SerialName注解太折腾,下面是几个实用的解决办法:
1. 配置自动兼容驼峰/下划线的命名策略(最省心)
直接修改Ktor客户端的Json序列化配置,让它自动在两种命名格式之间转换,不用再手动调整实体类的注解:
install(ContentNegotiation) { json(Json { prettyPrint = true isLenient = true // 兼容格式不严谨的JSON ignoreUnknownKeys = true // 忽略服务端新增的未知字段 explicitNulls = false // 自定义命名策略,同时兼容驼峰和下划线格式 namingStrategy = object : JsonNamingStrategy { // 实体类驼峰字段转下划线(发送请求时使用) override fun serialNameForName(name: String): String { return name.replace(Regex("(?<=[a-z])[A-Z]")) { "_${it.value.lowercase()}" } } // 服务端字段(驼峰/下划线)转实体类驼峰(解析响应时使用) override fun nameForSerialName(serialName: String): String { return if (serialName.contains("_")) { serialName.split("_").mapIndexed { index, part -> if (index == 0) part else part.replaceFirstChar { it.uppercase() } }.joinToString("") } else { serialName } } } }) }
配置完成后,实体类可以直接使用驼峰字段名,无需添加@SerialName注解,不管服务端返回originalName还是original_name都能正常解析:
@Serializable data class FileUploadResponseData( val path: String, val originalName: String? = null // 加默认值,避免字段缺失直接报错 )
2. 给敏感字段设置默认值
对于服务端可能随时改名或暂时缺失的字段,将其设为可空类型并赋予默认值,这样就算字段不匹配也不会直接抛出异常,后续再逐步调整:
@Serializable data class FileUploadResponseData( val path: String, val originalName: String? = null // 可空+默认值,提升容错性 )
3. 优化错误日志,减少排查时间
修改Ktor的日志配置,把序列化异常的详情单独打印出来,一眼就能定位到问题字段:
install(Logging) { level = LogLevel.ALL logger = object : Logger { override fun log(message: String) { if (message.contains("JsonConvertException")) { Log.e("Ktor Serialize Error", message) } else { Log.d("Ktor Log", message) } } } }
额外提醒
最好跟服务端开发团队提前约定字段命名规范(比如统一用下划线或驼峰),从根源减少这类反复改代码的情况;开发阶段也可以使用Mock数据测试,不用依赖不稳定的服务端API。
内容的提问来源于stack exchange,提问作者Segrei Ulanov
相关产品推荐
相关产品推荐

