如何为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
相关产品推荐
相关产品推荐

