You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Kotlin协程驱动中@Contextual注解类型添加MongoDB序列化器?

如何为MongoDB Kotlin协程驱动配置自定义SerializersModule

我在使用Kotlinx Serialization和MongoDB Kotlin协程驱动时遇到了问题:用Json序列化带LocalDate的实体类时,通过serializersModule添加LocalDateSerializer可以正常运行,但插入MongoDB时却触发序列化异常,提示找不到LocalDate的序列化器。

代码示例

@Serializable
data class D(@Contextual val d: LocalDate)

fun main() {
    val d = D(LocalDate.now())
    val json = Json {
        serializersModule += SerializersModule {
            contextual(LocalDateSerializer)
        }
    }
    println(json.encodeToString(d)) // {"d":"2024-04-09"}

    val client = MongoClient.create(url)
    val test = client.getDatabase("web-im")
        .getCollection<D>("test")

    runBlocking {
        test.insertOne(d) // 报错
    }
}

报错信息

Exception in thread "main" kotlinx.serialization.SerializationException: Serializer for class 'LocalDate' is not found.
Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.

解决方案

当然可以把你的LocalDateSerializer添加到MongoDB Kotlin驱动使用的序列化配置中。MongoDB Kotlin协程驱动允许你通过CodecRegistry自定义序列化逻辑,具体步骤如下:

  • 创建包含LocalDateSerializer的SerializersModule(和Json序列化时的配置一致)
  • 使用KotlinxSerializationCodecProvider将该模块转换为MongoDB兼容的CodecRegistry
  • 在创建MongoClient时,将自定义的CodecRegistry设置为默认编解码器注册表

修改后的完整代码:

@Serializable
data class D(@Contextual val d: LocalDate)

fun main() {
    val d = D(LocalDate.now())
    val json = Json {
        serializersModule += SerializersModule {
            contextual(LocalDateSerializer)
        }
    }
    println(json.encodeToString(d)) // {"d":"2024-04-09"}

    // 1. 定义自定义SerializersModule
    val customSerializersModule = SerializersModule {
        contextual(LocalDateSerializer)
    }

    // 2. 转换为MongoDB的CodecRegistry
    val codecRegistry = fromRegistries(
        MongoClientSettings.getDefaultCodecRegistry(),
        KotlinxSerializationCodecProvider(customSerializersModule).getCodecRegistry()
    )

    // 3. 配置MongoClient并应用自定义CodecRegistry
    val client = MongoClient.create(
        MongoClientSettings.builder()
            .applyConnectionString(ConnectionString(url))
            .codecRegistry(codecRegistry)
            .build()
    )

    val test = client.getDatabase("web-im")
        .getCollection<D>("test")

    runBlocking {
        test.insertOne(d) // 正常执行插入
    }
}

说明

KotlinxSerializationCodecProvider是MongoDB Kotlin驱动提供的桥接类,它能将Kotlinx Serialization的SerializersModule转换为MongoDB的CodecRegistry,这样MongoDB在处理实体类的序列化/反序列化时,就会使用你指定的LocalDateSerializer,解决找不到序列化器的问题。

内容的提问来源于stack exchange,提问作者Jin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:23:33