C#存储含List<object>属性对象到MongoDB时序列化反序列化异常
问题根本原因
你遇到的异常是两个核心原因共同导致的:
- 你的
TableHeaderKey属性声明为List<object>类型,MongoDB默认Bson序列化器处理未知类型时,会自动添加_t(类型鉴别符,存储完整类型名)和_v(实际值存储字段)标记封装数据 - Newtonsoft.Json的
JToken系列类型(JObject/JArray/JValue)没有提供MongoDB序列化器所需的无参构造和集合元素添加方法,反序列化时无法构造对应实例,因此抛出异常
解决方案
方案1(最推荐,无兼容问题):修改属性为强类型
根据你给出的原始数据结构,TableHeaderKey的每个元素都是「键为字符串、值为int数组」的字典结构,直接修改属性类型即可完全避免类型识别问题:
public class Result { public int Type { get; set; } public string Key { get; set; } public string Table{get;set;} // 替换原来的List<object>声明 public List<Dictionary<string, int[]>> TableHeaderKey {get;set;} public List<LocationVariance> locationVariance { get; set; } }
修改后赋值时直接往TableHeaderKey中插入Dictionary<string, int[]>实例即可,不需要转换为JObject,MongoDB默认序列化器会直接生成你期望的无标记格式,反序列化也不会报错。
方案2:保留JObject类型,调整序列化逻辑
如果你的业务逻辑必须使用JObject/List<object>的结构,可以修改存取逻辑绕开默认Bson序列化的问题:
写入时先转JSON再转Bson
public async Task<T> Add<T>(T obj, string collectionName) { var session = __client.StartSession(); // 先通过Newtonsoft序列化为JSON,再转成BsonDocument,避免生成_t/_v标记 string json = JsonConvert.SerializeObject(obj); var document = BsonDocument.Parse(json); session.StartTransaction(); var collection = __database.GetCollection<BsonDocument>(collectionName); await collection.InsertOneAsync(document); session.CommitTransaction(); }
读取时先转JSON再反序列化
public async Task<Result> GetResult(ObjectId id) { var collection = __database.GetCollection<BsonDocument>("你的集合名称"); var filter = Builders<BsonDocument>.Filter.Eq("_id", id); BsonDocument doc = await collection.Find(filter).FirstOrDefaultAsync(); // 先转JSON再用Newtonsoft反序列化,绕开Bson原生序列化的限制 string json = doc.ToJson(); return JsonConvert.DeserializeObject<Result>(json); }
方案3:兼容已存储的带_t/_v标记的旧数据
如果已经有大量旧数据写入无法修改,可以自定义Bson序列化器,专门处理TableHeaderKey属性的反序列化逻辑,解析_t和_v字段映射为你需要的结构,注册到MongoDB序列化配置中即可。
内容的提问来源于stack exchange,提问作者Brijen Patel
相关产品推荐
相关产品推荐

