Android Kotlin:修改LoginBody字段名,需保留新旧版本并支持切换
轻量解决方案:两种LoginBody字段格式切换实现
方案一:扩展函数+区分命名数据类(适合需显式区分类实例的场景)
首先为避免类名冲突,给新版数据类做命名区分:
// 原有驼峰字段版本 data class LoginBody( var username: String, var password: String, var deviceType: String, var deliveryPlatform: String, var osName: String, var deviceId: String ) // 新版下划线字段版本,命名做区分 data class LoginBodySnakeCase( var username: String, var password: String, var device_type: String, var client_platform: String, var os_name: String, var device_id: String )
通过扩展函数实现双向转换:
// 旧版转新版 fun LoginBody.toSnakeCaseVersion() = LoginBodySnakeCase( username = this.username, password = this.password, device_type = this.deviceType, client_platform = this.deliveryPlatform, os_name = this.osName, device_id = this.deviceId ) // 新版转旧版(如需回退兼容) fun LoginBodySnakeCase.toCamelCaseVersion() = LoginBody( username = this.username, password = this.password, deviceType = this.device_type, deliveryPlatform = this.client_platform, osName = this.os_name, deviceId = this.device_id )
最后根据启动场景的开关决定使用哪个版本:
// 全局开关,可从启动参数、环境变量或配置文件读取 val useSnakeCaseLogin = false // true则用新版,false用旧版 // 使用示例 fun submitLogin(originalBody: LoginBody) { val requestBody = if (useSnakeCaseLogin) { originalBody.toSnakeCaseVersion() } else { originalBody } // 后续将requestBody传入接口请求 }
方案二:序列化策略切换(无需新增类,更轻量,适合接口参数序列化场景)
如果你的场景是和后端交互时需要不同的字段名格式,推荐直接通过序列化框架的配置实现,不需要新增数据类。以Gson为例:
步骤1:给原有LoginBody字段添加多序列化别名
data class LoginBody( var username: String, var password: String, @SerializedName(value = "deviceType", alternate = ["device_type"]) var deviceType: String, @SerializedName(value = "deliveryPlatform", alternate = ["client_platform"]) var deliveryPlatform: String, @SerializedName(value = "osName", alternate = ["os_name"]) var osName: String, @SerializedName(value = "deviceId", alternate = ["device_id"]) var deviceId: String )
步骤2:创建不同序列化策略的Gson实例
// 旧版:使用驼峰字段名序列化 val gsonCamel = GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) .create() // 新版:自动将驼峰字段转为下划线格式 val gsonSnake = GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .create()
步骤3:根据场景切换Gson实例
val useSnakeCase = true // 启动场景决定该值 // 序列化示例 fun serializeLoginRequest(body: LoginBody): String { return if (useSnakeCase) { gsonSnake.toJson(body) } else { gsonCamel.toJson(body) } } // 反序列化示例(兼容两种格式的响应) fun deserializeLoginResponse(json: String): LoginBody { // 因为添加了alternate注解,两种格式的响应都能正常解析 return gsonCamel.fromJson(json, LoginBody::class.java) }
这个方案不需要修改现有大量使用LoginBody的业务代码,仅在序列化/反序列化环节切换配置,完全满足轻量需求,且旧版本废弃后只需移除旧的Gson实例和注解即可。
内容的提问来源于stack exchange,提问作者Kratos
相关产品推荐
相关产品推荐

