Kotlin Kmongo库通过抽象类Message获取多态子类实例集合如何实现
KMongo抽象类多态反序列化实现方案
KMongo底层依赖Jackson实现数据的序列化/反序列化,要实现抽象类自动映射到对应子类实例,需要给抽象类添加Jackson多态类型注解,序列化时会自动写入类型标识,反序列化时根据标识自动构建对应子类对象,具体实现步骤如下:
步骤1:给模型类添加多态配置注解
提供两种常用配置方案,可根据需求选择:
方案1:使用全类名作为类型标识(配置最简单)
import com.fasterxml.jackson.annotation.JsonTypeInfo import org.litote.kmongo.Data @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) abstract class Message : Data data class TextMessage(val m: String): Message() data class ImageMessage(val m: ByteArray): Message()
该方案会自动在Mongo文档中新增@class字段,存储子类的全限定类名,反序列化时自动根据该字段生成对应子类实例,适合不需要兼容类路径变更的场景。
方案2:使用自定义别名作为类型标识(灵活兼容性强)
import com.fasterxml.jackson.annotation.JsonSubTypes import com.fasterxml.jackson.annotation.JsonTypeInfo import com.fasterxml.jackson.annotation.JsonTypeName import org.litote.kmongo.Data @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "msgType") @JsonSubTypes( JsonSubTypes.Type(value = TextMessage::class, name = "text"), JsonSubTypes.Type(value = ImageMessage::class, name = "image") ) abstract class Message : Data @JsonTypeName("text") data class TextMessage(val m: String): Message() @JsonTypeName("image") data class ImageMessage(val m: ByteArray): Message()
该方案会在Mongo文档中新增msgType字段,存储自定义的类型别名,可读性更好,后续重构包名/类名也不会影响历史数据反序列化。
步骤2:直接使用原有代码操作集合
完成注解配置后不需要修改原有业务代码,直接按你预设的逻辑操作即可:
// 获取Message类型集合 val collection = database.getCollection<Message>() // 插入数据时直接传入子类实例即可,会自动写入类型标识 collection.insertOne(TextMessage("测试文本消息")) collection.insertOne(ImageMessage(byteArrayOf(1,2,3))) // 查询时会自动反序列化为对应子类实例,类型判断逻辑完全可用 when(val value = collection.findOne()) { is TextMessage -> { /* 处理文本消息逻辑 */ } is ImageMessage -> { /* 处理图片消息逻辑 */ } else -> {} }
注意事项
- 如果存在没有类型标识的历史数据,可以给
@JsonTypeInfo添加defaultImpl参数指定默认反序列化类型,避免反序列化报错。 - ByteArray类型不需要额外配置,KMongo默认会将其映射为Mongo的BinData类型存储。
内容的提问来源于stack exchange,提问作者user16799920
相关产品推荐
相关产品推荐

