如何将Kotlin的NullableStringSerializer改造为通用序列化器?
解决方案
方法一:全局配置解码转换器(最简便)
无需编写自定义序列化器,直接在Json配置中添加全局解码转换器,将所有空字符串的JSON元素转为JsonNull,可空类型会自动解析为null:
val json = Json { decodeTransformers += JsonTransformer { element -> if (element is JsonPrimitive && element.isString && element.content.isEmpty()) { JsonNull } else { element } } }
之后使用标准可空类型数据类即可,无需额外注解:
@Serializable data class Foo(val bar: Long?)
方法二:通用泛型序列化器(按需绑定)
如果仅需对特定字段生效,可编写通用泛型序列化器,配合工厂函数和委托object实现:
- 定义通用序列化器类
class NullableStringToNullSerializer<T>(private val delegate: KSerializer<T>) : KSerializer<T?> { override val descriptor: SerialDescriptor = delegate.descriptor.nullable override fun serialize(encoder: Encoder, value: T?) { value?.let(delegate::serialize) ?: encoder.encodeNull() } override fun deserialize(decoder: Decoder): T? { val element = decoder.decodeJsonElement() return if (element is JsonPrimitive && element.isString && element.content.isEmpty()) { null } else { delegate.deserialize(JsonDecoder(decoder.json, element)) } } companion object { inline fun <reified T> create(): KSerializer<T?> = NullableStringToNullSerializer(serializer()) } }
- 为需要的类型创建委托object(仅需一行代码)
object LongNullableStringSerializer : KSerializer<Long?> by NullableStringToNullSerializer.create<Long>() object IntNullableStringSerializer : KSerializer<Int?> by NullableStringToNullSerializer.create<Int>()
- 在数据类中使用
@Serializable data class Foo(@Serializable(with = LongNullableStringSerializer::class) val bar: Long?)
方法三:泛型JsonTransformingSerializer配合工厂函数
利用JsonTransformingSerializer特性,结合reified类型参数的工厂函数:
class GenericNullableStringSerializer<T>(serializer: KSerializer<T>) : JsonTransformingSerializer<T>(serializer) { override fun transformDeserialize(element: JsonElement): JsonElement = if (element is JsonPrimitive && element.isString && element.content.isEmpty()) JsonNull else element companion object { inline fun <reified T> create(): KSerializer<T> = GenericNullableStringSerializer(serializer()) } }
使用时通过委托object间接引用(注解无法直接使用函数返回值):
object LongNullableTransformer : KSerializer<Long?> by GenericNullableStringSerializer.create<Long?>() @Serializable data class Foo(@Serializable(with = LongNullableTransformer::class) val bar: Long?)
内容的提问来源于stack exchange,提问作者majkrzak
相关产品推荐
相关产品推荐

