C#使用Newtonsoft反序列化MongoDB ObjectId出现转换错误如何解决
问题根因
你遇到的报错及自定义Converter未触发的核心原因有两个:
document.ToJson()默认输出的是MongoDB扩展格式的非标准JSON,_id字段会输出为ObjectId("xxx")的语法,而不是标准JSON的字符串格式。Newtonsoft.Json在解析到第一个字符O时就会判定为非法JSON直接抛出异常,还未走到调用自定义Converter的逻辑,因此你写的MongoDataSerializer永远不会被触发。- 你自定义的Converter是用于处理字符串转
ObjectId的逻辑,但当前输入的JSON根本不符合标准结构,解析第一步就失败了。
最优解决方案(推荐,无需走JSON序列化中转)
完全不需要把BsonDocument转成JSON再反序列化,直接用MongoDB官方提供的Bson序列化方法即可,性能更高且不会出现格式兼容问题:
- 如果你最终需要
_id以字符串形式存在,直接修改模型定义即可,无需自定义Converter:
public class BTMObj { // 直接定义为string类型,MongoDB序列化器会自动将ObjectId转为字符串 public string _id { get; set; } public string requestFormat { get; set; } }
- 你甚至可以直接获取对应类型的集合,省去手动转换的步骤,
GetMongoCollection方法可以简化为:
public List<T> GetMongoCollection<T>(string collectionName) { try { var client = new MongoClient(Convert.ToString(ConfigurationManager.AppSettings["MONGO_CONNECTION"])); var database = client.GetDatabase(Convert.ToString(ConfigurationManager.AppSettings["MONGO_DB"])); // 直接获取对应类型的集合,无需中转BsonDocument和JSON var collection = database.GetCollection<T>(collectionName); return collection.Find(FilterDefinition<T>.Empty).ToList(); } catch (Exception ex) { throw; } }
如果需要保留原来遍历BsonDocument的逻辑,替换转换代码即可:
list.Add(BsonSerializer.Deserialize<T>(document));
兼容原有JSON转换逻辑的解决方案
如果你必须保留用Newtonsoft.Json反序列化的逻辑,需要先把ToJson的输出改为标准JSON格式:
- 调用
ToJson时传入配置,输出严格模式的标准JSON:
var json = document.ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict });
此时输出的JSON中_id会变为标准格式:"_id": {"$oid": "611cf42e1e4c89336b6fe2f0"}
2. 调整你的自定义Converter逻辑适配$oid结构,或者直接使用MongoDB官方为Newtonsoft.Json提供的ObjectIdConverter即可触发转换逻辑。
内容的提问来源于stack exchange,提问作者Ronak
相关产品推荐
相关产品推荐

