C# 字典<;字符串,对象>-到b忽略字段的声文档转换
我正在使用C# 字典<;字符串,对象>-到b忽略字段的声文档转换,c#,mongodb,dictionary,bson,C#,Mongodb,Dictionary,Bson,我正在使用MongoDB.Bson中的ToBsonDocument扩展方法来转换此词典: var dictionary = new Dictionary<string, object> {{"person", new Dictionary<string, object> {{"name", "John"}}}}; var document = dictionary.ToBsonDocument(); 有没有办法摆脱这些东西?我希望生成的文
MongoDB.Bson
中的ToBsonDocument
扩展方法来转换此词典:
var dictionary = new Dictionary<string, object> {{"person", new Dictionary<string, object> {{"name", "John"}}}};
var document = dictionary.ToBsonDocument();
有没有办法摆脱这些东西?我希望生成的文档如下所示:
{ "person" : { "name" : "John" } }
UPD:我在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;
}
因此,当值类型为
object
时,此序列化程序似乎没有太多选项,这是因为您为字典值指定了object
类型,但实际为特定记录值使用了dictionary
类型。因此,CSharp驱动程序保存了具体类型的全名,以便将来正确地反序列化此文档。您还可以在此处阅读更多信息:
要获得所需结果,应为字典值指定具体类型:
var dictionary = new Dictionary<string, Dictionary<string, object>>
{
{ "person", new Dictionary<string, object> { { "name", "John" } } }
};
var document = dictionary.ToBsonDocument();
var字典=新字典
{
{“人”,新字典{{“名字”,“约翰”}
};
var document=dictionary.ToBsonDocument();
您应首先序列化为JSON,然后再序列化为BSON
var jsonDoc = Newtonsoft.Json.JsonConvert.SerializeObject(dictionary);
var bsonDoc = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(jsonDoc);
var jsonDoc=Newtonsoft.Json.JsonConvert.SerializeObject(字典);
var bsonDoc=MongoDB.Bson.Serialization.BsonSerializer.Deserialize(jsonDoc);
从对象到BSON的直接转换很困难
而是从object-->Json-->Bson开始
// Object --> JSON
using System.Web.Extensions;
using System.Web;
using System.Web.Script.Serialization;
JavaScriptSerializer js = new JavaScriptSerializer();
string json = js.Serialize(poco); // poco is ur class object
//JSON --> BSON
MongoDB.Bson.BsonDocument document = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(json);
//对象-->JSON
使用System.Web.Extensions;
使用System.Web;
使用System.Web.Script.Serialization;
JavaScriptSerializer js=新的JavaScriptSerializer();
字符串json=js.Serialize(poco);//poco是您的类对象
//JSON-->BSON
MongoDB.Bson.BsonDocument document=MongoDB.Bson.Serialization.BsonSerializer.Deserialize(json);
从.NET对象到JSON再到BSON,同时避免_t/_v编码,将导致日期和其他BSON特定类型的类型信息丢失
我找到的在保留BSON类型的同时避免_t/_v的解决方案是为驱动程序的内置字典InterfaceImplementerSerializer
(以及可选的枚举接口实现器serializer
)注册一个自定义值序列化器。我已经测试了“扩展JSON”生成的解决方案,即针对BSON特定类型使用特殊语法的JSON,但对于直接BSON输出,原理应该是相同的
为此,首先将标准的ObjectSerializer
复制到您的C#project中(并将其重命名以避免歧义):
除了类重命名之外,private void serializedValue(BsonSerializationContext,BsonSerializationArgs args,object value,Type actualType)
方法也需要编辑。(在我的例子中,我还希望避免对IEnumerable
进行_t/_v编码,如下所示。)
请注意,必须为每个实际类型执行此操作,其值应用于。无法对接口进行序列化程序注册。因此,如果SortedDictionary
或SortedList
与Dictionary
的处理方式相同,则需要对这些类型重复注册。(这会影响在这些类型的集合中作为值包含的字典是否将在没有_t/_v的情况下序列化,而不一定影响这些类型的对象本身是否将以这种方式序列化。)
要将相同的序列化原则应用于列表
对象,请使用以下注册码
BsonSerializer.RegisterSerializer(typeof(List<object>),
new EnumerableInterfaceImplementerSerializer<List<object>, object>(
new DynamicValueSerializer()));
BsonSerializer.RegisterSerializer(类型(列表),
新的EnumerableInterfaceImplementerSerializer(
新的DynamicValueSerializer());
是的,如果我为值指定具体类型,它可以正常工作。但在我的例子中,任何值都可以是字符串
值或另一个字典
。因此,对于类型,我似乎只能使用object
。我可以要求司机在这种情况下也这样做吗?我看不出有什么办法。谢谢你的解决方案。效果很好。
private void SerializeDiscriminatedValue(BsonSerializationContext context, BsonSerializationArgs args, object value, Type actualType)
{
var serializer = BsonSerializer.LookupSerializer(actualType);
var polymorphicSerializer = serializer as IBsonPolymorphicSerializer;
// Added line
var assignableToDictionaryOrEnumerable = typeof(IDictionary<string, object>).IsAssignableFrom(actualType) || typeof(IEnumerable<object>).IsAssignableFrom(actualType);
if (polymorphicSerializer != null && polymorphicSerializer.IsDiscriminatorCompatibleWithObjectSerializer)
{
serializer.Serialize(context, args, value);
}
else
{
// Edited line
if (assignableToDictionaryOrEnumerable || (context.IsDynamicType != null && context.IsDynamicType(value.GetType())))
{
// We want this code to be executed for types that should be serialized without _t and _v fields
args.NominalType = actualType;
serializer.Serialize(context, args, value);
}
else
{
var bsonWriter = context.Writer;
var discriminator = _discriminatorConvention.GetDiscriminator(typeof(object), actualType);
bsonWriter.WriteStartDocument();
bsonWriter.WriteName(_discriminatorConvention.ElementName);
BsonValueSerializer.Instance.Serialize(context, discriminator);
bsonWriter.WriteName("_v");
serializer.Serialize(context, value);
bsonWriter.WriteEndDocument();
}
}
}
BsonSerializer.RegisterSerializer(typeof(Dictionary<string, object>),
new DictionaryInterfaceImplementerSerializer<Dictionary<string, object>, string, object>(
DictionaryRepresentation.Document,
new StringSerializer(),
new DynamicValueSerializer()));
BsonSerializer.RegisterSerializer(typeof(List<object>),
new EnumerableInterfaceImplementerSerializer<List<object>, object>(
new DynamicValueSerializer()));