Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary<string, object>-to-BsonDocument conversion omitting _t field

I'm using ToBsonDocument extension method from MongoDB.Bson to convert this Dictionary:

        var dictionary = new Dictionary<string, object> {{"person", new Dictionary<string, object> {{"name", "John"}}}};
        var document = dictionary.ToBsonDocument();

And here's the resulting document:

  { "person" : 
      { "_t" : "System.Collections.Generic.Dictionary`2[System.String,System.Object]", 
        "_v" : { "name" : "John" } } }

Is there a way to get rid of these _t/_v stuff? I would like the resulting document to look like this:

  { "person" : { "name" : "John" } }

UPD: I've found the code in DictionaryGenericSerializer:

if (nominalType == typeof(object))
{
    var actualType = value.GetType();
    bsonWriter.WriteStartDocument();
    bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType));
    bsonWriter.WriteName("_v");
    Serialize(bsonWriter, actualType, value, options); // recursive call replacing nominalType with actualType
    bsonWriter.WriteEndDocument();
    return;
}

So, it seems that there are not too many options with this serializer when the value type is object.

like image 336
vorou Avatar asked Nov 05 '13 10:11

vorou


2 Answers

You shall first serialize to JSON and then to BSON,

var jsonDoc = Newtonsoft.Json.JsonConvert.SerializeObject(dictionary);
var bsonDoc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(jsonDoc);
like image 118
selvan Avatar answered Sep 28 '22 22:09

selvan


That is happen because you specify object type for dictionary values, but actually use Dictionary<string, object> type for the particular record value. Therefore, CSharp driver saves the full name of concrete type to deserialize this document properly in future. You can also read more about it here: Serialize Documents with the CSharp Driver: Polymorphic Classes and Discriminators

To achieve desired result you should specify concrete type for dictionary values:

var dictionary = new Dictionary<string, Dictionary<string, object>>
{
    { "person", new Dictionary<string, object> { { "name", "John" } } }
};
var document = dictionary.ToBsonDocument();
like image 28
Shad Avatar answered Sep 28 '22 23:09

Shad