我正在制作一种自动将数据持久存储到磁盘上的数据 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)

Kotlin相关问答推荐

我如何测试一个可组合组件没有显示,但如果它不存在也接受?

解决Microronaut中多个可能的Bean候选者冲突

仅某些用户出现 DateTimeFormatter 错误

垂直滚动条下拉菜单的桌面组合

创建包含 3 个相同项目的列表/使用返回类型重复

Kotlin 函数中接收者和参数的类型相同

Kotlin 函数有 2 个参数用于对 Map 或 List 进行排序

Kotlin 使用委托进行隐式覆盖

从 Kotlin 调用 Java 时可以为空的规则是什么

JavaFX - 你如何在 Kotlin 中使用 MapValueFactory?

从字符串列表构建字符串

Kotlin - mutableMapOf() 会保留我输入的顺序

将 Firebase 数据快照反序列化为 Kotlin 数据类

以编程方式重新启动 Spring Boot 应用程序/刷新 Spring 上下文

片段内的 Kotlin 按钮 onClickListener 事件

如何在 Jetpack Compose 的 LazyColumn/LazyRow 中禁用和启用滚动?

kotlin 委托有什么用?

使用 kotlin 每 3 位数添加逗号或点

我应该在哪里调用 MobileAds.initialize()?

Kotlin 中的填充字符串