C# 如何将MongoDB聚合查询返回的BsonDocument转为JSON输出到浏览器
.NET 4.5.2 + MVC4 环境下MongoDB聚合结果返回标准JSON解决方案
适用依赖版本
- .NET Framework 4.5.2 + MVC4
- MongoDB.Driver 2.11.1
- Newtonsoft.Json 11.0.2
问题根因
之前尝试的方案报错核心原因如下:
- 直接将
List<BsonDocument>赋值给JsonResult.Data时,MVC默认JSON序列化器无法识别Bson结构,会触发二次序列化或输出异常结构,导致前端收到带转义符的字符串 - 反序列化报错是因为C#模型定义的字段类型和MongoDB中存储的字段类型不匹配,例如MongoDB中存储为int的字段,模型定义为string就会触发类型转换异常
- 调用
ToJson()后再赋值给JsonResult.Data会触发二次序列化,最终返回被转义的JSON字符串
方案一:强类型模型适配(推荐)
步骤1:定义匹配MongoDB字段类型的模型
给模型添加Bson序列化注解,保证字段类型和MongoDB存储的类型完全一致:
using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; public class FolderTree { // 适配MongoDB默认的_id字段,自动将ObjectId转为字符串 [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } // 其他字段类型和MongoDB存储类型保持一致,例如存的是int就用int,不要用string public string FolderName { get; set; } public int SortOrder { get; set; } public List<FolderTree> Children { get; set; } }
步骤2:执行聚合查询直接映射为强类型
执行聚合时直接指定泛型类型,省略手动反序列化步骤:
// pipeline为你已定义的聚合管道 var folderList = mongoCollection.Aggregate<FolderTree>(pipeline).ToList();
步骤3:直接返回标准JSON
使用Newtonsoft.Json序列化后通过ContentResult返回,避免MVC默认序列化二次处理:
using Newtonsoft.Json; using System.Web.Mvc; public ContentResult GetFolderTreeData() { // 省略聚合查询逻辑,得到folderList string jsonResult = JsonConvert.SerializeObject(folderList); return Content(jsonResult, "application/json"); }
方案二:无模型直接转换BsonDocument
如果不需要定义业务模型,可以直接将Bson结果转为标准JSON返回:
using MongoDB.Bson; using MongoDB.Bson.IO; using System.Web.Mvc; public ContentResult GetFolderTreeData() { // 执行聚合得到BsonDocument列表 var bsonList = mongoCollection.Aggregate<BsonDocument>(pipeline).ToList(); // 配置序列化设置,移除MongoDB专属类型标记,输出标准JSON var jsonSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict, Indent = false }; string jsonResult = bsonList.ToJson(jsonSettings); return Content(jsonResult, "application/json"); }
注意事项
- 不要将已经序列化完成的JSON字符串赋值给
JsonResult.Data,该操作会触发二次序列化,必然产生转义符 - 如果出现类型转换错误,可通过MongoDB Compass查看集合中对应字段的实际存储类型,和模型定义保持一致即可解决
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

