草庐IT

C# MongoDB 复杂类序列化

coder 2023-10-29 原文

我正在使用 C# MongoDB 驱动程序,我要保存这个相当复杂的 JSON 结构:

{
    "name" : "value",
    "age": 1,
    "isFemale": true,
    "Hobbies" : {
        //All data within the "Hobbies" node is dynamic
        //and may change from one item to another.
        "stringItem" : "value",
        "intItem" : 0.0,
        "listOfItems" : [
            { "field" : 1696.0 }
        ],
        "intArray" : [ 566.0,  1200.0 ]
    },
    "Collection" : [ 
        //All data within the "Collection" node is dynamic
        //and may change from one item to another.
        {
            "field" : "string",
            "FieldTypeId" : 2.0,
            "array" : [ 
                { "value" : "1024x1000" }
            ]
        }
    ]
}

我有代表上述对象的这个类:

public class MyClass
{
    public string Name;
    public int Age;
    public bool IsFemale;
    public Dictionary<string, object> Hobbies;
    public List<Dictionary<string, object>> Collection;
}

这是我为“爱好”部分保存的内容:

"Hobbies": {
    "stringItem": "value",
    "intItem": 1,
    "listOfItems": {
        "_t": "Newtonsoft.Json.Linq.JArray, Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed",
        "_v": [{
            "_t": "JObject",
            "_v": [{
                "_t": "JProperty",
                "_v": [{
                    "_t": "JValue",
                    "_v": []
                }]
            },
            {
                "_t": "JProperty",
                "_v": [{
                    "_t": "JValue",
                    "_v": []
                }]
            }]
        }]
    }
}

我的猜测是我应该为该类编写一个自定义序列化程序,但我在 MONGODB .NET DRIVER Manual 中找不到任何有用的示例

我试图开始并实现这样的事情:

public class MyClassSerializer : SerializerBase<MyClass>, IBsonDocumentSerializer
{
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, MyClass value)
    {
        //What to do here???
        base.Serialize(context, args, value);
    }

    public override MyClass Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        //What to do here???
        return base.Deserialize(context, args);
    }

    public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo)
    {
        switch (memberName)
        {
            case "Name":
                serializationInfo = new BsonSerializationInfo(memberName, new StringSerializer(), typeof(string));
                return true;
            case "Age":
                serializationInfo = new BsonSerializationInfo(memberName, new Int16Serializer(), typeof(string));
                return true;
            case "IsFemale":
                serializationInfo = new BsonSerializationInfo(memberName, new BooleanSerializer(), typeof(string));
                return true;
            case "Hobbies":
                serializationInfo = new BsonSerializationInfo(memberName, new TupleSerializer<string, object>(), typeof(string));
                return true;
            case "Collection":
                serializationInfo = new BsonSerializationInfo(memberName, new ArraySerializer<Dictionary<string, object>>(), typeof(string));
                return true;
            default:
                serializationInfo = null;
                return false;
        }
    }
}

但我找不到与此相关的任何内容。它没有完全实现,我读到我需要在某处注册序列化器,但是在哪里...?

最佳答案

处理此问题且无需创建额外属性的简单方法是注册自定义序列化程序。

ComplexTypeSerializer.cs

namespace MyNamespace.MongoDB.Serializers
{
    public class ComplexTypeSerializer : SerializerBase<object>
    {
        public override object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            var serializer = BsonSerializer.LookupSerializer(typeof(BsonDocument));
            var document = serializer.Deserialize(context, args);

            var bsonDocument = document.ToBsonDocument();

            var result = BsonExtensionMethods.ToJson(bsonDocument);
            return JsonConvert.DeserializeObject<IDictionary<string, object>>(result);
        }

        public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
        {
            var jsonDocument = JsonConvert.SerializeObject(value);
            var bsonDocument = BsonSerializer.Deserialize<BsonDocument>(jsonDocument);

            var serializer = BsonSerializer.LookupSerializer(typeof(BsonDocument));
            serializer.Serialize(context, bsonDocument.AsBsonValue);
        }
    }
}

并按照http://mongodb.github.io/mongo-csharp-driver/2.3/reference/bson/serialization/注册

BsonSerializer.RegisterSerializer(typeof(IDictionary<string, object>), new ComplexTypeSerializer());

BsonSerializer.RegisterSerializer(typeof(IList<IDictionary<string, object>>), new ComplexTypeSerializer());

下面的代码是用一个简单的 IDictionary<string, object> 测试的。 ,不确定它是否适用于 IList<IDictionary<string, object>> ,但是如果它不受支持,您可以创建另一个自定义序列化程序来支持它。

关于C# MongoDB 复杂类序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47510650/

有关C# MongoDB 复杂类序列化的更多相关文章

  1. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  2. ruby - 使用 AES 的 Rails 加密,过于复杂 - 2

    我在加密来self正在使用的第三方供应商的值时遇到问题。他们的指令如下:1)Converttheencryptionpasswordtoabytearray.2)Convertthevaluetobeencryptedtoabytearray.3)Theentirelengthofthearrayisinsertedasthefirstfourbytesontothefrontofthefirstblockoftheresultantbytearraybeforeencryption.4)EncryptthevalueusingAESwith:1.256-bitkeysize,2.25

  3. ruby - 在 Ruby 中比较序列 - 2

    假设我必须(小型到中型)阵列:tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]如何确定tokens是否以相同的顺序包含template的所有条目?(请注意,在上面的示例中,应忽略第一个“ccc”,从而由于最后一个“ccc”而导致匹配。) 最佳答案 这适用于您的示例数据。tokens=["aaa","ccc","xxx","bbb","ccc","yyy","zzz"]template=["aaa","bbb","ccc"]po

  4. ruby - 测试一个复杂的方法 - 2

    我正在开发西洋跳棋实现,其中有许多易于测试的方法,但我不确定如何测试我的主要#play_game方法。我的大多数方法都可以很容易地确定输入和输出,因此也很容易测试,但这种方法是多方面的,实际上并没有容易辨别的输出。这是代码:defplay_gameputs@gui.introwhile(game_over?==false)message=nil@gui.render_board(@board)@gui.move_requestplayer_input=getscoordinates=UserInput.translate_move_request_to_coordinates(play

  5. ruby - 是否有用于复杂比较的漂亮语法? - 2

    方法应返回-1,0或1分别表示“小于”、“等于”和“大于”。对于某些类型的可排序对象,通常将排序顺序基于多个属性。以下是可行的,但我认为它看起来很笨拙:classLeagueStatsattr_accessor:points,:goal_diffdefinitializepts,gd@points=pts@goal_diff=gdenddefothercompare_pts=pointsother.pointsreturncompare_ptsunlesscompare_pts==0goal_diffother.goal_diffendend尝试一下:[LeagueStats.new(

  6. ruby-on-rails - carrierwave:在序列化动态属性上安装 uploader - 2

    首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟

  7. ruby-on-rails - 如何构建复杂的 Rails 系统 - 2

    关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭8年前。Improvethisquestion我们有以下(以及更多)系统,我们将数据从一个应用推送/拉取到另一个:托管CRM(InsideSales.com)Asterisk电话系统(内部)横幅广告系统(openx,我们托管)潜在客户生成系统(自行开发)电子商务商店(spree,我们托管)工作板(本土)一些工作网站抓取+入站工作提要电子邮件传送系统(如Mailchimp,自主开发)事件管理系统(如eventbrite,自主开发)仪表板系统(大量图表和

  8. 机器学习——时间序列ARIMA模型(四):自相关函数ACF和偏自相关函数PACF用于判断ARIMA模型中p、q参数取值 - 2

    文章目录1、自相关函数ACF2、偏自相关函数PACF3、ARIMA(p,d,q)的阶数判断4、代码实现1、引入所需依赖2、数据读取与处理3、一阶差分与绘图4、ACF5、PACF1、自相关函数ACF自相关函数反映了同一序列在不同时序的取值之间的相关性。公式:ACF(k)=ρk=Cov(yt,yt−k)Var(yt)ACF(k)=\rho_{k}=\frac{Cov(y_{t},y_{t-k})}{Var(y_{t})}ACF(k)=ρk​=Var(yt​)Cov(yt​,yt−k​)​其中分子用于求协方差矩阵,分母用于计算样本方差。求出的ACF值为[-1,1]。但对于一个平稳的AR模型,求出其滞

  9. ruby-on-rails - Rails 编辑序列化的 JSON 数据 - 2

    我有一个存储JSON数据的列。当它处于编辑状态时,我不知道如何显示它。serialize:value,JSON=f.fields_for:valuedo|ff|.form-group=ff.label:short=ff.text_field:short,class:'form-control'.form-group=ff.label:long=ff.text_field:long,class:'form-control' 最佳答案 代替=f.fields_for:valuedo|ff|请使用以下代码:=f.fields_for:va

  10. ruby - 了解 Ruby Enumerable#map(具有更复杂的 block ) - 2

    假设我有一个函数defodd_or_evennifn%2==0return:evenelsereturn:oddendend我有一个简单的可枚举数组simple=[1,2,3,4,5]然后我用我的函数在map中运行它,使用一个do-endblock:simple.mapdo|n|odd_or_even(n)end#=>[:odd,:even,:odd,:even,:odd]如果不首先定义函数,我怎么能做到这一点?例如,#doesnotworksimple.mapdo|n|ifn%2==0return:evenelsereturn:oddendend#Desiredresult:#=>[

随机推荐