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

MongoDB文档反序列化C#对象时referrals属性报错,如何忽略异常文档?

解决MongoDB反序列化部分文档报错的问题

针对你遇到的部分文档中referrals字段类型不匹配(字符串而非List<ObjectId?>)导致的反序列化错误,这里有几个可行的方案:

方案1:查询时先过滤不符合格式的文档

既然问题出在部分文档的referrals是字符串类型,我们可以在查询阶段就把这些文档排除掉。MongoDB支持按字段类型筛选,只保留referrals为数组的文档:

var usersCollection = MongoConnectionHandler.GetDB().GetCollection<User>("users");
// 筛选出referrals字段类型为数组的文档
var filter = Builders<User>.Filter.Type(u => u.referrals, BsonType.Array);
var myusers = usersCollection.Find(filter).AsQueryable();

这样遍历的时候就只会处理符合类型要求的文档,直接避开有问题的那些。

方案2:自定义序列化器处理类型不匹配的情况

如果不想丢弃这些文档,而是希望在反序列化时自动处理错误(比如把字符串类型的referrals转为null或空列表),可以给referrals字段自定义一个序列化器:

首先创建自定义序列化器类:

public class NullableObjectIdListSerializer : SerializerBase<List<ObjectId?>>
{
    public override List<ObjectId?> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonReader = context.Reader;
        var currentBsonType = bsonReader.GetCurrentBsonType();

        // 如果是字符串类型,跳过该值并返回null(也可返回空列表)
        if (currentBsonType == BsonType.String)
        {
            bsonReader.ReadString();
            return null;
        }
        // 如果是数组,用默认序列化器处理
        else if (currentBsonType == BsonType.Array)
        {
            var defaultSerializer = new EnumerableInterfaceImplementerSerializer<List<ObjectId?>, ObjectId?>(new NullableSerializer<ObjectId>(new ObjectIdSerializer()));
            return defaultSerializer.Deserialize(context, args);
        }
        // 其他未知类型也跳过并返回null
        else
        {
            bsonReader.SkipValue();
            return null;
        }
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, List<ObjectId?> value)
    {
        // 序列化逻辑沿用默认实现即可
        var defaultSerializer = new EnumerableInterfaceImplementerSerializer<List<ObjectId?>, ObjectId?>(new NullableSerializer<ObjectId>(new ObjectIdSerializer()));
        defaultSerializer.Serialize(context, args, value);
    }
}

然后在User类的referrals字段上应用这个序列化器:

[BsonIgnoreExtraElements]
public class User : MongoEntity {
    [BsonDefaultValue(null)]
    [BsonSerializer(typeof(NullableObjectIdListSerializer))]
    public List<ObjectId?> referrals { get; set; }
}

这样反序列化时遇到字符串类型的referrals就会自动跳过,不会抛出异常,你可以保留这些文档,只是referrals会被设为null或空列表。

方案3:全局配置错误容忍(谨慎使用)

如果你希望全局处理这类反序列化错误,也可以配置MongoDB驱动的反序列化错误策略,但这种方式会影响所有反序列化操作,可能掩盖其他潜在问题,需谨慎使用:

var settings = new BsonSerializerSettings
{
    IgnoreExtraElements = true,
    // 遇到反序列化错误时忽略并继续
    DeserializationErrorHandling = DeserializationErrorHandling.IgnoreAndContinue
};

// 获取集合时指定自定义序列化配置
var users = MongoConnectionHandler.GetDB().GetCollection<User>("users", 
    new MongoCollectionSettings { SerializerRegistry = BsonSerializerRegistry.Create(settings) });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:39:50