zoukankan      html  css  js  c++  java
  • 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());
        });
    }
    
  • 相关阅读:
    Vue项目和微信小程序项目的区别与比较
    在Vue中应该如何封装Axios 管理API接口
    Vue2.x 项目踩坑笔记
    微信小程序日常踩坑笔记
    面试题之JavaScript 请写一个深度克隆的函数
    面试题之JavaScript 请编写实现一个对js类型检测函数(支持检测基本类型,对象,函数,正则,时间等)
    面试题之 HTML && CSS && JavaScript 总结
    面试题之JavaScript 有一个url 'http://www.youdao.com/newcard.html?sid=50&a=5&add=9&type=all',请写一个获取url中'?'后制定参数值的函数
    面试题之JavaScript 请给Array本地对象增加一个原型方法,它用于删除数组条目中重复的条目(可能有多个),返回值是一个包含被删除的重复条目的新数组。
    面试题之JavaScript 正则相关题
  • 原文地址:https://www.cnblogs.com/yyzq/p/13626703.html
Copyright © 2011-2022 走看看