Serialize Dictionary to BSON documents

2019-07-10 02:57发布

I want to serialize Dictionary<long, VALUE> to following JSON in MongoDB.

{
   "213" : {},
   "63624" : {},
   ...
}

I don't want other DictionaryRepresentation except DictionaryRepresentation.Document.Document

I am using MongoDB C# Driver (v2.0.1.27), and it is not smart to convert the long type key into string, which causes an exception.

Thank you

2条回答
Lonely孤独者°
2楼-- · 2019-07-10 03:14

You can do this with the existing serializers but it requires a small amount of configuration.

Assume the following class:

public class C
{
    public int Id { get; set; }
    public Dictionary<long, long> D { get; set; }
}

You can configure a custom serializer for the D property (the Dictionary) that uses a key serializer that serializes longs to strings. The code would look like this:

BsonClassMap.RegisterClassMap<C>(cm =>
{
    cm.AutoMap();
    var customDictionarySerializer = new DictionaryInterfaceImplementerSerializer<Dictionary<long, long>>(
        dictionaryRepresentation: DictionaryRepresentation.Document,
        keySerializer: new Int64Serializer(BsonType.String),
        valueSerializer: BsonSerializer.SerializerRegistry.GetSerializer<long>());
    cm.GetMemberMap(c => c.D).SetSerializer(customDictionarySerializer);
});

The key idea here is that even though the keys and values are both longs, we are using different serializers for the keys and the values.

If we then run a quick test:

var document = new C { Id = 1, D = new Dictionary<long, long> { { 2, 3 } } };
var json = document.ToJson();
Console.WriteLine(json);

We see that the Dictionary keys are now being serialized as strings:

{ "_id" : 1, "D" : { "2" : NumberLong(3) } }
查看更多
够拽才男人
3楼-- · 2019-07-10 03:35

Also I worked out another solution, hope it helps other people

public class LongDictionarySerializer<K> : DictionarySerializerBase<Dictionary<long, K>>
{
    public LongDictionarySerializer() : base(DictionaryRepresentation.Document)
    {
    }

    protected override Dictionary<long, K> CreateInstance()
    {
        return new Dictionary<long, K>();
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Dictionary<long, K> value)
    {
        if (value != null)
        {
            Dictionary<string, K> dic = value.ToDictionary(d => d.Key.ToString(), d => d.Value);
            BsonSerializer.Serialize<Dictionary<string, K>>(context.Writer, dic);
        }
        else
            BsonSerializer.Serialize<object>(context.Writer, null);
    }
    public override Dictionary<long, K> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        Dictionary<string, K> dic = BsonSerializer.Deserialize<Dictionary<string, K>>(context.Reader);
        if (dic == null)
            return null;

        Dictionary<long, K> ret = new Dictionary<long, K>();
        foreach( var pair in dic )
        {
            long key;
            if (!long.TryParse(pair.Key, out key))
                continue;
            ret[key] = pair.Value;
        }
        return ret;
    }
}

Then on the field

[BsonElement(Fields.Markets)]
[BsonSerializer(typeof(LongDictionarySerializer<XXX>))]
public Dictionary<long, XXX> Markets { get; set; }
查看更多
登录 后发表回答