我正在制作一个自动将数据保存到磁盘的数据结构。为此,我使用 kotlinx-serialization。有没有办法要求泛型类型具有@Serializabe注释?
class PersistentList <@Serializable E> () : List<E> {...}
该示例无法编译。希望你明白我的意思。我想限制 E 有注释。有办法做到吗?
最佳答案
KSerializer
构造函数参数
您可以添加KSerializer
对于 E
在 PersistentList
的构造函数中.
class PersistentList<E>(
elementSerializer: KSerializer<E>
) : List<E> {
// ...
}
虽然更详细,但它比向 E
添加注释更有优势。 - 可以分配自定义序列化程序,这意味着 PersistentList
可能包含来自外部代码但没有 @Serializable
的类注释。
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()
为了使其更加自动化,您可以使用 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)
关于kotlin - 有什么方法可以要求在 kotlin 中的类型参数上添加注释吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74604364/