asp.net core 3.1中对Mongodb BsonDocument的序列化和反序列化支持
最近项目使用了Mongodb作为非结构化数据的存储,大量使用了
BsonDocument
做为传输对象,但是面临一个问题,直接把BsonDocument
通过web api返回前端时候,并不能序列化为期望的json;同样把json传输到后台也不能自动把json组装成BsonDocument
。
为此实现了一个自定义的asp.net core 3.1的JsonConverter
来处理BsonDocument
的序列化和反序列化。
首先定义一个BsonDocument
的转换对象,并且实现JsonConverter<T>
。
public class BsonDocumentJsonConverter : JsonConverter<BsonDocument>
{
/// <summary>
/// 反序列化支持
/// </summary>
/// <param name="reader"></param>
/// <param name="typeToConvert"></param>
/// <param name="options"></param>
/// <returns></returns>
public override BsonDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
using (var stream = new MemoryStream())
{
using (Utf8JsonWriter writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }))
{
jsonDoc.WriteTo(writer);
writer.Flush();
string json = Encoding.UTF8.GetString(stream.ToArray());
return BsonDocument.Parse(json);
}
}
}
}
/// <summary>
/// 序列化支持
/// </summary>
/// <param name="writer"></param>
/// <param name="value"></param>
/// <param name="options"></param>
public override void Write(Utf8JsonWriter writer, BsonDocument value, JsonSerializerOptions options)
{
if (value == null)
{
writer.WriteStringValue(String.Empty);
}
else
{
WirteJson(writer, value);
}
}
private void WirteJson(Utf8JsonWriter writer, BsonDocument bson)
{
writer.WriteStartObject();
var elements = bson.Elements;
foreach (var item in elements)
{
WirteProperty(writer, item.Value, item.Name);
}
writer.WriteEndObject();
}
private void WirteProperty(Utf8JsonWriter writer, BsonValue bsonValue, string propertyName=null)
{
BsonType bsonType = bsonValue.BsonType;
switch (bsonType)
{
case BsonType.EndOfDocument:
break;
case BsonType.Int32:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteNumberValue(bsonValue.AsInt32);
}
else
{
writer.WriteNumber(propertyName, bsonValue.AsInt32);
}
break;
case BsonType.Int64:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteNumberValue(bsonValue.AsInt64);
}
else
{
writer.WriteNumber(propertyName, bsonValue.AsInt64);
}
break;
case BsonType.Double:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteNumberValue(bsonValue.AsDouble);
}
else
{
writer.WriteNumber(propertyName, bsonValue.AsDouble);
}
break;
case BsonType.String:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteStringValue(bsonValue.AsString);
}
else
{
writer.WriteString(propertyName, bsonValue.AsString);
}
break;
case BsonType.Document:
if (string.IsNullOrEmpty(propertyName))
{
WirteJson(writer, bsonValue.AsBsonDocument);
}
else
{
writer.WritePropertyName(propertyName);
WirteJson(writer, bsonValue.AsBsonDocument);
}
break;
case BsonType.Array:
if (string.IsNullOrEmpty(propertyName))
{
var bsonArr = bsonValue.AsBsonArray;
writer.WriteStartArray();
foreach (var abson in bsonArr)
{
WirteProperty(writer, abson);
}
writer.WriteEndArray();
}
else
{
var bsonArr = bsonValue.AsBsonArray;
writer.WritePropertyName(propertyName);
writer.WriteStartArray();
foreach (var abson in bsonArr)
{
WirteProperty(writer, abson);
}
writer.WriteEndArray();
}
break;
case BsonType.Boolean:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteBooleanValue(bsonValue.AsBoolean);
}
else
{
writer.WriteBoolean(propertyName, bsonValue.AsBoolean);
}
break;
case BsonType.DateTime:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteStringValue(bsonValue.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:sszzz"));
}
else
{
writer.WriteString(propertyName, bsonValue.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:sszzz"));
}
break;
case BsonType.Null:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteNullValue();
}
else
{
writer.WriteNull(propertyName);
}
break;
case BsonType.ObjectId:
if (string.IsNullOrEmpty(propertyName))
{
writer.WriteStringValue(bsonValue.AsObjectId.ToString());
}
else
{
writer.WriteString(propertyName, bsonValue.AsObjectId.ToString());
}
break;
case BsonType.RegularExpression:
break;
case BsonType.JavaScript:
break;
case BsonType.Symbol:
break;
case BsonType.JavaScriptWithScope:
break;
case BsonType.Decimal128:
break;
case BsonType.MinKey:
break;
case BsonType.MaxKey:
break;
case BsonType.Timestamp:
break;
case BsonType.Binary:
break;
case BsonType.Undefined:
break;
default:
break;
}
}
}
最后在Startup.cs
文件中注册该转换器就好了
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddControllersWithViews().AddJsonOptions(option => {
//....
option.JsonSerializerOptions.Converters.Add(new BsonDocumentJsonConverter());
});
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库