如何为包含HttpUrl、Cookie等自定义对象的Map编写KSerializer
正确实现Map<HttpUrl, List>的自定义KSerializer
你之前的实现存在两个核心问题:
@Serializer(forClass = Map::class)泛型匹配错误,且使用PrimitiveSerialDescriptor描述非基础类型的Map结构,和实际序列化结构不匹配- 没有实现HttpUrl、Cookie和可序列化基础类型的转换逻辑
完整实现代码
import kotlinx.serialization.* import kotlinx.serialization.builtins.* import kotlinx.serialization.descriptors.* import kotlinx.serialization.encoding.* import okhttp3.HttpUrl import okhttp3.Cookie @Serializer(forClass = Map::class) object CookieSerializer : KSerializer<Map<HttpUrl, List<Cookie>>> { override val descriptor: SerialDescriptor = MapSerialDescriptor( serialName = "CookieMap", keyDescriptor = PrimitiveSerialDescriptor("HttpUrl", PrimitiveKind.STRING), valueDescriptor = ListSerialDescriptor( elementDescriptor = PrimitiveSerialDescriptor("Cookie", PrimitiveKind.STRING) ) ) override fun serialize(encoder: Encoder, value: Map<HttpUrl, List<Cookie>>) { // 将自定义类型转换为可序列化的基础类型结构 val serializableMap = value.mapKeys { it.key.toString() } .mapValues { entry -> entry.value.map { cookie -> cookie.toString() } } encoder.encodeSerializableValue(serializer<Map<String, List<String>>>(), serializableMap) } override fun deserialize(decoder: Decoder): Map<HttpUrl, List<Cookie>> { // 先反序列化得到基础类型结构,再转换为目标类型 val serializableMap = decoder.decodeSerializableValue(serializer<Map<String, List<String>>>()) return serializableMap.mapKeys { entry -> HttpUrl.get(entry.key) } .mapValues { entry -> entry.value.mapNotNull { cookieStr -> // 每个Cookie解析绑定对应所属的HttpUrl Cookie.parse(entry.key, cookieStr) } } } }
使用说明与注意事项
- 字段绑定方式无需修改,保持原有
@Serializable(with = CookieSerializer::class)标记cookies字段即可 - 反序列化过程中
mapNotNull会自动过滤解析失败的Cookie,如果你需要严格校验格式,可以将其替换为判空抛出异常的逻辑 - 如果需要保留Cookie的所有自定义属性,你可以单独声明一个可序列化的Cookie数据类,将Cookie的name、value、domain、expiresAt等属性抽出来单独序列化,避免
Cookie.toString()丢失非标准属性 - 请确保项目中已经正确引入kotlinx-serialization插件和相关依赖,否则会出现内置序列化器找不到的错误
内容的提问来源于stack exchange,提问作者Vipul
相关产品推荐
相关产品推荐

