如何为Kotlinx.serialization设置全局驼峰式字段命名策略
解决Kotlinx.serialization多命名格式统一转小驼峰的问题
核心思路
要同时兼容大驼峰(如ProjectName)、下划线式(如project_name)的JSON键反序列化为Kotlin小驼峰属性,同时序列化时输出小驼峰格式,需实现自定义双向命名策略,配合兜底配置避免未知键异常,全程保留Kotlin原生小驼峰代码风格。
实现步骤
1. 自定义命名策略类
实现JsonNamingStrategy,重写序列化和反序列化的命名转换逻辑,确保两种输入格式都能转为小驼峰:
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialElement import kotlinx.serialization.json.JsonNamingStrategy class UniversalCamelCaseNamingStrategy : JsonNamingStrategy { // 序列化:Kotlin小驼峰属性直接输出为小驼峰JSON键 override fun serialName(descriptor: SerialDescriptor, element: SerialElement): String { return element.name } // 反序列化:将输入的大驼峰/下划线JSON键转为小驼峰 override fun deserializedName(descriptor: SerialDescriptor, element: SerialElement): String { return convertToLowerCamelCase(element.name) } private fun convertToLowerCamelCase(input: String): String { return when { // 处理下划线格式:project_name -> projectName input.contains("_") -> input.split("_") .mapIndexed { index, part -> if (index == 0) part.lowercase() else part.replaceFirstChar { it.uppercase() } } .joinToString("") // 处理大驼峰格式:ProjectName -> projectName input.firstOrNull()?.isUpperCase() == true -> input.replaceFirstChar { it.lowercase() } // 已是小驼峰,直接返回 else -> input } } }
2. 配置全局Json实例
创建Json实例时指定自定义策略,同时开启未知键忽略兜底:
import kotlinx.serialization.json.Json val json = Json { namingStrategy = UniversalCamelCaseNamingStrategy() ignoreUnknownKeys = true // 兜底处理未覆盖的极端键格式 encodeDefaults = true // 可选,按需决定是否序列化默认值 }
3. 测试验证
定义标准小驼峰Kotlin数据类:
import kotlinx.serialization.Serializable @Serializable data class Project( val projectName: String, val projectId: Int )
以下三种JSON格式均可正常反序列化:
- 大驼峰JSON:
{ "ProjectName": "Kotlin Serialization", "ProjectId": 123 }
- 下划线JSON:
{ "project_name": "Kotlin Serialization", "project_id": 123 }
- 小驼峰JSON:
{ "projectName": "Kotlin Serialization", "projectId": 123 }
调用json.decodeFromString<Project>(jsonString)即可完成解析,序列化时输出标准小驼峰JSON。
关键注意事项
- 反序列化的转换逻辑是核心,需覆盖所有预期的输入键格式
ignoreUnknownKeys为兜底配置,主要依赖命名策略处理常规格式- 全程保留Kotlin小驼峰代码风格,无侵入式修改,完全兼容原有代码
内容的提问来源于stack exchange,提问作者otuva
相关产品推荐
相关产品推荐

