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

如何指定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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:06:34