将 Dictionary<long, VALUE> 序列化为 BSON 文档
Serialize Dictionary<long, VALUE> to BSON documents
我想将 Dictionary<long, VALUE>
序列化到 MongoDB 中的 JSON 之后。
{
"213" : {},
"63624" : {},
...
}
除了DictionaryRepresentation.Document.Document
我不想要其他DictionaryRepresentation
我使用的是MongoDB C# Driver (v2.0.1.27),将long
类型的key转成string
不智能,导致异常。
您可以使用现有的序列化程序执行此操作,但它需要少量配置。
假设以下 class:
public class C
{
public int Id { get; set; }
public Dictionary<long, long> D { get; set; }
}
您可以为 D 属性(字典)配置自定义序列化程序,该序列化程序使用将 long 序列化为字符串的密钥序列化程序。代码如下所示:
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);
});
这里的关键思想是即使键和值都是 long,我们对键和值使用不同的序列化器。
如果我们然后 运行 快速测试:
var document = new C { Id = 1, D = new Dictionary<long, long> { { 2, 3 } } };
var json = document.ToJson();
Console.WriteLine(json);
我们看到字典键现在被序列化为字符串:
{ "_id" : 1, "D" : { "2" : NumberLong(3) } }
我也想出了一个办法,希望对其他人有帮助
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;
}
}
然后在场上
[BsonElement(Fields.Markets)]
[BsonSerializer(typeof(LongDictionarySerializer<XXX>))]
public Dictionary<long, XXX> Markets { get; set; }
我想将 Dictionary<long, VALUE>
序列化到 MongoDB 中的 JSON 之后。
{
"213" : {},
"63624" : {},
...
}
除了DictionaryRepresentation.Document.Document
DictionaryRepresentation
我使用的是MongoDB C# Driver (v2.0.1.27),将long
类型的key转成string
不智能,导致异常。
您可以使用现有的序列化程序执行此操作,但它需要少量配置。
假设以下 class:
public class C
{
public int Id { get; set; }
public Dictionary<long, long> D { get; set; }
}
您可以为 D 属性(字典)配置自定义序列化程序,该序列化程序使用将 long 序列化为字符串的密钥序列化程序。代码如下所示:
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);
});
这里的关键思想是即使键和值都是 long,我们对键和值使用不同的序列化器。
如果我们然后 运行 快速测试:
var document = new C { Id = 1, D = new Dictionary<long, long> { { 2, 3 } } };
var json = document.ToJson();
Console.WriteLine(json);
我们看到字典键现在被序列化为字符串:
{ "_id" : 1, "D" : { "2" : NumberLong(3) } }
我也想出了一个办法,希望对其他人有帮助
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;
}
}
然后在场上
[BsonElement(Fields.Markets)]
[BsonSerializer(typeof(LongDictionarySerializer<XXX>))]
public Dictionary<long, XXX> Markets { get; set; }