如何指定MongoClient将嵌入式文档解码为自定义Java类型Type1_?
解决MongoDB自定义Codec解码嵌套Type1_字段的问题
你已经正确实现了Type1_的自定义Codec并完成了注册,但解码环节出错是因为直接用Document.get()不会触发Mongo的Codec机制来转换嵌套字段。下面给你两种可行的解决方案:
方案一:手动使用Codec解码字段
既然你已经把Type1_Codec注册到了MongoClient,就可以从CodecRegistry中取出该Codec,手动解码Document中的对应字段:
@Test public void demonstrate_simpleCustomCodec() { final MongoClient mongoClient = buildMongoClientWithCustomCodec(CustomCodecRegistriesFactory.getDefaultWithType1_()); final MongoDatabase db = mongoClient.getDatabase("db_" + new SecureRandom().nextInt(Integer.MAX_VALUE)); final String collectionName = "col1"; db.createCollection(collectionName); final MongoCollection<Document> col1 = db.getCollection(collectionName); int idCounter = 0; final String type1_field = "type1_"; printTitle("Inserting Documents"); for (int i = 0; i < 10; i++) { col1.insertOne(new Document(ID, idCounter++).append(type1_field, Type1_.random())); } printDocumentMongoCollection(col1); printMongoCollectionJackson(col1); printTitle("Attempting Decoding"); // --- 修正后的解码逻辑 --- // 获取已注册的CodecRegistry CodecRegistry codecRegistry = mongoClient.getCodecRegistry(); // 取出Type1_对应的Codec Codec<Type1_> type1Codec = codecRegistry.get(Type1_.class); // 查询第一个文档 Document doc = col1.find().first(); if (doc != null) { // 获取type1_字段对应的BsonDocument BsonDocument type1Bson = doc.get(type1_field, BsonDocument.class); // 使用Codec完成解码 try (BsonReader reader = new BsonDocumentReader(type1Bson)) { Type1_ type1_value = type1Codec.decode(reader, DecoderContext.builder().build()); System.out.println(type1_value); } } }
方案二:使用泛型MongoCollection和实体类(更优雅)
定义一个和Mongo文档结构完全对应的实体类,让Mongo驱动自动帮你完成编码和解码操作:
1. 创建对应文档结构的实体类
public class MyDocument { @BsonId // 标记为文档的ID字段 private int id; private Type1_ type1_; // 无参构造器(Mongo驱动反射实例化需要) public MyDocument() {} // 带参构造器 public MyDocument(int id, Type1_ type1_) { this.id = id; this.type1_ = type1_; } // Getter和Setter方法 public int getId() { return id; } public void setId(int id) { this.id = id; } public Type1_ getType1_() { return type1_; } public void setType1_(Type1_ type1_) { this.type1_ = type1_; } }
2. 修改测试代码使用泛型集合
@Test public void demonstrate_simpleCustomCodec() { final MongoClient mongoClient = buildMongoClientWithCustomCodec(CustomCodecRegistriesFactory.getDefaultWithType1_()); final MongoDatabase db = mongoClient.getDatabase("db_" + new SecureRandom().nextInt(Integer.MAX_VALUE)); final String collectionName = "col1"; db.createCollection(collectionName); // 使用泛型MongoCollection<MyDocument>替代原生Document集合 final MongoCollection<MyDocument> col1Typed = db.getCollection(collectionName, MyDocument.class); int idCounter = 0; printTitle("Inserting Documents"); for (int i = 0; i < 10; i++) { // 直接插入MyDocument对象,驱动会自动调用Type1_Codec编码嵌套字段 col1Typed.insertOne(new MyDocument(idCounter++, Type1_.random())); } printTitle("Attempting Decoding"); // 直接查询,驱动会自动调用Type1_Codec解码嵌套字段 MyDocument firstDoc = col1Typed.find().first(); if (firstDoc != null) { Type1_ type1_value = firstDoc.getType1_(); System.out.println(type1_value); } }
为什么原来的代码会失败?
你注释的col1.find().first().get(type1_field, Type1_.class)之所以报错,核心原因是:Document的get方法不会调用你注册的自定义Codec——它只会尝试把Bson值(比如BsonDocument)直接强制转换为目标类型,而这种默认转换逻辑并不支持你的自定义Type1_类,因此会抛出类型转换异常。
内容的提问来源于stack exchange,提问作者user5132301
相关产品推荐
相关产品推荐

