我正在制作一种自动将数据持久存储到磁盘上的数据 struct .为此,我使用kotlinx序列化.有没有办法要求泛型类型具有@Serializabe注释?
class PersistentList <@Serializable E> () : List<E> {...}
这个例子不能编译.希望你明白我的意思.我希望将E约束为具有注释.有办法做到这一点吗?
我正在制作一种自动将数据持久存储到磁盘上的数据 struct .为此,我使用kotlinx序列化.有没有办法要求泛型类型具有@Serializabe注释?
class PersistentList <@Serializable E> () : List<E> {...}
这个例子不能编译.希望你明白我的意思.我希望将E约束为具有注释.有办法做到这一点吗?
KSerializer
constructor parameter在PersistentList
的构造函数中为E
添加一个KSerializer
.
class PersistentList<E>(
elementSerializer: KSerializer<E>
) : List<E> {
// ...
}
虽然更冗长,但与向E
添加批注相比,它有一个优势--可以分配一个定制的串行化程序,这意味着PersistentList
可以包含来自外部代码的没有@Serializeable
批注的类.
import kotlinx.serialization.KSerializer
// Assume this class is from another library, meaning @Serializable cannot be added
data class SomeExternalData(
val name: String
}
// Create a custom serializer for SomeExternalData
object SomeExternalDataSerializer : KSerializer<SomeExternalData> {
// ...
}
fun main() {
// Since a serializer is required, the `E` must be serializable
val persistentList = PersistentList(SomeExternalDataSerializer)
}
class PersistentList< E: PersistentElement>(
elementSerializer: KSerializer<E>,
) : List<E> {
// ...
}
这是确保E
可序列化的唯一可行方法.
串行器模块.串行器()
为了使其更自动化,您可以使用SerializersModule
,它有一个函数serializer()
,可以通过反射魔法获取序列化程序.
可以创建一个工作方式类似于Json.encodeToString(...)
的扩展函数,它将自动确定特定格式的序列化程序.
/** Automatically determine the serializable type of [PersistentList] */
inline fun <reified T> SerialFormat.createPersistentList(): PersistentList<SomeData> =
PersistentList(serializersModule.serializer())
但是,这不会触发任何编译时判断.
下面是一个更完整的例子:
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialFormat
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
@Serializable
data class SomeData(
val name: String
)
fun main() {
val persistentList = Json.createPersistentList(listOf(
SomeData("1"), SomeData("2"), SomeData("3"),
))
println(persistentList)
val encoded = Json.encodeToString(persistentList.listSerializer, persistentList.actualList)
println(encoded)
}
class PersistentList<E>(
elementSerializer: KSerializer<E>,
val actualList: List<E>,
) : List<E> by actualList {
val listSerializer = ListSerializer(elementSerializer)
}
inline fun <reified E> SerialFormat.createPersistentList(actualList: List<E>): PersistentList<E> =
PersistentList(serializersModule.serializer(), actualList)