如何为Kotlin Serializer实现动态SerialName注解?
Kotlin Serialization 实现动态字段名(动态SerialName)
要实现动态变化的字段名,直接修改@SerialName注解是行不通的——因为注解是编译期确定的,无法在运行时动态变更。正确的做法是给整个WeatherResponse类编写自定义序列化器,在序列化/反序列化阶段动态处理字段名。
你的自定义序列化器问题分析
你之前写的序列化器是针对String类型的,完全没覆盖WeatherResponse的结构逻辑,这才导致了Field 'weatherData' is required的错误。而且你的序列化逻辑错误地尝试编码两个字符串元素,和实际API返回的“动态键对应WeatherData对象”的结构不匹配。
正确实现方案
假设你的WeatherData定义如下:
@Serializable data class WeatherData(val temp: Double, val humidity: Int)
给WeatherResponse编写自定义序列化器:
@Serializable(with = WeatherResponseSerializer::class) data class WeatherResponse(val weatherData: WeatherData) object WeatherResponseSerializer : KSerializer<WeatherResponse> { override val descriptor = SerialDescriptor("com.test.WeatherResponse", SerialKind.Structure) override fun serialize(encoder: Encoder, value: WeatherResponse) { val dynamicFieldName = getWeatherID() encoder.encodeStructure(descriptor) { // 传入动态字段名,序列化WeatherData encodeSerializableElement(descriptor, 0, WeatherData.serializer(), value.weatherData, dynamicFieldName) } } override fun deserialize(decoder: Decoder): WeatherResponse { val dynamicFieldName = getWeatherID() return decoder.decodeStructure(descriptor) { var targetData: WeatherData? = null while (true) { val index = decodeElementIndex(descriptor) if (index == CompositeDecoder.DECODE_DONE) break // 匹配动态字段名 if (decodeElementName(descriptor, index) == dynamicFieldName) { targetData = decodeSerializableElement(descriptor, index, WeatherData.serializer()) } else { // 跳过其他未知字段,避免解析失败 skipElement(descriptor, index) } } // 校验必填字段 targetData ?: throw SerializationException("Missing required field: $dynamicFieldName") }.let { WeatherResponse(it) } } // 这里替换成你实际获取动态字段名的逻辑 // 比如根据之前的API响应、全局状态等返回对应字段名 private fun getWeatherID(): String { return "some_weather_id" // 示例值,可动态返回"another_weather_id"等 } }
关键逻辑说明
- 绑定序列化器:通过
@Serializable(with = ...)指定WeatherResponse使用自定义序列化器 - 序列化阶段:调用
encodeSerializableElement时传入动态字段名,将weatherData序列化为对应键的对象 - 反序列化阶段:遍历所有字段,通过
decodeElementName匹配动态字段名,找到后解析WeatherData;其他未知字段直接跳过 - 必填校验:最后检查目标字段是否存在,不存在则抛出序列化异常
内容的提问来源于stack exchange,提问作者OdinsBeard
相关产品推荐
相关产品推荐

