kotlinx.serialization.SerializationException:找不到类“UnitEntity”(myClassName)的序列化程序

Posted

技术标签:

【中文标题】kotlinx.serialization.SerializationException:找不到类“UnitEntity”(myClassName)的序列化程序【英文标题】:kotlinx.serialization.SerializationException: Serializer for class 'UnitEntity' (myClassName) is not found 【发布时间】:2021-03-30 23:37:00 【问题描述】:

我正在开发一个 Kotlin 多平台项目,但遇到了保存数据库实体对象的问题。当我调用我的 sqldelight dao 类的插入方法时抛出异常

kotlinx.serialization.SerializationException: Serializer for class 'UnitEntity' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
    at kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered(Platform.common.kt:91)
    at kotlinx.serialization.internal.PlatformKt.platformSpecificSerializerNotRegistered(Platform.kt:29)
    at kotlinx.serialization.SerializersKt__SerializersKt.serializer(Serializers.kt:59)
    at kotlinx.serialization.SerializersKt.serializer(Unknown Source:1)
.....

那个例子类就是生成的实体类

import com.example.package.core.entity.UnitEntity;
import com.example.package.core.entity.ResourceTypeEntity;

CREATE TABLE IF NOT EXISTS `ResourceEntity` (
`id` TEXT NOT NULL,
`name` TEXT NOT NULL,
`unitEntity` TEXT AS UnitEntity NOT NULL,
`type` TEXT AS ResourceTypeEntity NOT NULL,
PRIMARY KEY(`id`));

CREATE TABLE IF NOT EXISTS `ResourceTypeEntity` (
`typeId` TEXT NOT NULL,
`typeName` TEXT NOT NULL,
PRIMARY KEY(`typeId`)
);

CREATE TABLE IF NOT EXISTS `UnitEntity` (`unitId` TEXT NOT NULL, `unitName` TEXT NOT NULL, PRIMARY KEY(`unitId`));


save:
INSERT OR REPLACE INTO ResourceEntity
VALUES ?;

这里是 DAO 类:

 class ResourcesDaoImpl(private val dao: Resources_daoQueries) : ResourcesDao 
  override suspend fun save(resources: List<ResourceEntity>) 
    resources.forEach 
      dao.save(it)
    
  

当我尝试调用该保存方法时,它崩溃并说将该类标记为@Serializable,但我不明白它为什么这么说,因为它是一个生成的类,我无法修改这些类。

这是我如何尝试保存这些实体的 sn-p

val mappedData = itemsDto.map 
    ResourceEntity(
      id = it._id,
      name = it.name,
      type = ResourceTypeEntity(typeId = it.type._id, typeName = it.type.name),
      unitEntity = UnitEntity(unitId = it.unit._id, unitName = it.unit.unit)
    )
  
resourcesDao.save(mappedData)

图书馆:

val coroutinesVersion = "1.3.9-native-mt"
val ktor_version = "1.4.2"
val serializationVersion = "1.0.0-RC"
val koin_version = "3.0.0-alpha-4"
val sqlDelight = "1.4.4"

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion")
implementation("com.squareup.sqldelight:runtime:$sqlDelight")
// SqlDelight extension
implementation("com.squareup.sqldelight:coroutines-extensions:$sqlDelight")

这里是实际的entities 和由SqlDelight 生成的保存方法

data class ResourceTypeEntity(
  val typeId: String,
  val typeName: String
) 
  override fun toString(): String = """
  |ResourceTypeEntity [
  |  typeId: $typeId
  |  typeName: $typeName
  |]
  """.trimMargin()

RecourceEntity.class

import com.squareup.sqldelight.ColumnAdapter

data class ResourceEntity(
  val id: String,
  val name: String,
  val unitEntity: UnitEntity,
  val type: ResourceTypeEntity
) 
  override fun toString(): String = """
  |ResourceEntity [
  |  id: $id
  |  name: $name
  |  unitEntity: $unitEntity
  |  type: $type
  |]
  """.trimMargin()

  class Adapter(
    val unitEntityAdapter: ColumnAdapter<UnitEntity, String>,
    val typeAdapter: ColumnAdapter<ResourceTypeEntity, String>
  )

UnitEntity.class

data class UnitEntity(
  val unitId: String,
  val unitName: String
) 
  override fun toString(): String = """
  |UnitEntity [
  |  unitId: $unitId
  |  unitName: $unitName
  |]
  """.trimMargin()

保存方法

  override fun save(ResourceEntity: ResourceEntity) 
    driver.execute(-1658323214, """
     |INSERT OR REPLACE INTO ResourceEntity
     |VALUES (?, ?, ?, ?)
       """.trimMargin(), 7) 
          bindString(1, ResourceEntity.id)
          bindString(2, ResourceEntity.name)
          bindString(3,
          database.ResourceEntityAdapter.unitEntityAdapter.encode(ResourceEntity.unitEntity))
      bindString(4, database.ResourceEntityAdapter.typeAdapter.encode(ResourceEntity.type))
    
    notifyQueries(-1658323214, database.resources_daoQueries.getResources +
        database.resources_daoQueries.getResourceByManufacturerId)
  

【问题讨论】:

你的@Serializer 类上面有@Serializer 注释吗? 我无法添加注释,因为该类是由 SqlDelight 自动生成的 【参考方案1】:

您可以将注解添加到ResourceEntity:在UnitEntity 字段上方添加@Serializable(with = UnitEntitySerializer::class)

然后你需要定义UnitEntitySerializer 来实际帮助序列化它。这就是我在question/ answer 中使用 UUID 所做的。但是,我不确定UnitEntity 是什么,所以我不能帮你序列化它/写UnitEntitySerializer

【讨论】:

我无法在这些实体之上添加该注释,因为它是自动生成的类 “那些实体”?您只需要修改ResourceEntity。您不修改UnitEntity,而是修改ResourceEntity 中的above the UnitEntity field。你的意思是ResourceEntity 也生成了?在那种情况下,我必须回到github.com/Kotlin/kotlinx.serialization/blob/master/docs/… 具体看这里:github.com/Kotlin/kotlinx.serialization/blob/master/docs/… 是的,它也已生成,我只是将这些类添加到我的问题中。我会更详细地探索谢谢。

以上是关于kotlinx.serialization.SerializationException:找不到类“UnitEntity”(myClassName)的序列化程序的主要内容,如果未能解决你的问题,请参考以下文章