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
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) } }
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; }