简体   繁体   中英

mongodb C# driver serialize dynamic field on model

A concrete model class exists with a single dynamic field. This field could contain hundreds of COMPLEX data structures, and we won't be able to know what they are always.

public class Message {
    public dynamic MessageData { get; set; }
}

We can save this json from postman:

{
    "messageData": {
        "sdfghdfghjdfghdfg": {
            "sdfgsdfsdfghs": [
                {
                    "dfgfghkfghjfg": "4567456734573",
                    "dfjghjjkdehn": "fgjfghdfgjfhnfgh"
                }
            ],
            "hfgjkfguksdfgnuy": {}
        }
    }
  }

Our mongo find method shows this result:

{
{ "_id" : ObjectId("607605a7d42ba9fa20579745"),
 "MessageData" : { "_t" : "Newtonsoft.Json.Linq.JArray, Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed", "_v" : [ { "_t" : "JObject", "_v" : [ { "_t" : "JProperty", "_v" : [ { "_t" : "JObject", "_v" : [ { "_t" : "JProperty", "_v" : [ { "_t" : "JArray", "_v" : [ { "_t" : "JObject", "_v" : [ { "_t" : "JProperty", "_v" : [ { "_t" : "JValue", "_v" : [ ] } ] }, { "_t" : "JProperty", "_v" : [ { "_t" : "JValue", "_v" : [ ] } ] } ] } ] } ] }, { "_t" : "JProperty", "_v" : [ { "_t" : "JObject", "_v" : [ ] } ] } ] } ] } ] } ] }
}

When fetching the data we get this error:

System.FormatException: An error occurred while deserializing the MessageData property of class EMRPatientDB.Models.Message: Invalid element: '_t'.

The problem seems to be the MongoDB C# driver isn't serializing the JSON correctly?

Perhaps we want to write a custom serializer? But I haven't found a good example of how that is done for a JSON object.

I ran into this issue when I had a C# class with a property of type JObject .

My Solution was to create JObjectSerializer for MondoDB and add the attribute to the property so Mongo serializer uses it. I assume if I tried hard enough I could register the below serializer in Mongo as the global one for this type as well.

Register serializer for property processing:

[BsonSerializer(typeof(JObjectSerializer))]
public JObject AdditionalData { get; set; }

The serializer itself:

public class JObjectSerializer : SerializerBase<JObject> // IBsonSerializer<JObject>
{
    public override JObject Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var myBSONDoc = BsonDocumentSerializer.Instance.Deserialize(context);
        return JObject.Parse(myBSONDoc.ToString());
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, JObject value)
    {
        var myBSONDoc = MongoDB.Bson.BsonDocument.Parse(value.ToString());
        BsonDocumentSerializer.Instance.Serialize(context, myBSONDoc);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM