如何为方法 MongoDB.Bson.Serialization.BsonSerializer.Deserialize 自定义映射字段名称或类型

Posted

技术标签:

【中文标题】如何为方法 MongoDB.Bson.Serialization.BsonSerializer.Deserialize 自定义映射字段名称或类型【英文标题】:How to custom mapping fields name or type for method MongoDB.Bson.Serialization.BsonSerializer.Deserialize 【发布时间】:2019-06-26 15:27:22 【问题描述】:

我使用 MongoDB.Bson.Serialization.BsonSerializer.Deserialize() 方法将 MongoDB.Bson.BsonDocument 反序列化为 MyType。但该方法总是遇到 System.FormatException,因为 MyType 中的字段与 BsonDocument 中的字段不是 100% 匹配。

我尝试将复杂的 json 对象(我们称为 mobj)从 MongoDB(查询结果)转换为 C# 对象(我们称为 csobj),以便我可以处理数据。我使用的 csobj 中的默认数据类型是字符串。但是 mobj 太复杂了,我们对它的架构了解较少。

一旦在mobj中遇到BinData(0,"")、BinData(1,"")、BinData(2,"")、ISODate("")等数据类型,就有可能发生System.FormatException。

一旦 mobj 中有额外的新字段,可能会发生 System.FormatException。

一旦字段名称中有空格,例如“第一页”:“XXXX”,可能会发生 System.FormatException,我直到现在才知道如何解决。

var client = new MongoClient("mongodb://xxxxxx");
var database = client.GetDatabase("xxxxxxxxxx");
var collection = database.GetCollection<BsonDocument>("xxxxxxxxxx");

var results = await collection.Aggregate<BsonDocument>(filterBsonDocumentArray).ToListAsync();

foreach (var doc in results)

    var model = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<MyType>(doc); // always meet exception here

异常示例:

(mongodb 数据类型无法与字符串映射)

System.FormatException:反序列化 MongoQueryDemo.MyType 类的 Id 属性时出错:无法从 BsonType 'Binary' 反序列化 'String'。 ---> System.FormatException: 无法从 BsonType 'Binary' 反序列化 'String'。

(mongo中的_id在C#对象auto中找不到UserId)

System.FormatException:元素“_id”与 MongoQueryDemo.MyType 类的任何字段或属性都不匹配。

我的问题在这里列出:

    有没有办法告诉Deserializer,请不区分大小写;

    有没有办法自定义mobj到csobj的字段名映射,比如define "_id" --> UserId, "Ip Addr" --> "IpAddr";

    有没有办法自定义数据类型,让数据类型BinData(0,""), BinData(1,""), BinData(2,""), ISODate("") 都可以在没有 System.FormatException 的情况下转换为字符串;

    是否有任何方法可以将整个复杂的子对象映射到 C# 字符串,而不管其字段?由于它在模式较少的 mongodb 中是动态的,因此我无法在子对象中预定义任何未知字段。

【问题讨论】:

如果整个表的模式较少,为什么还要首先反序列化呢?将其用作BsonDocument,您可以像.GetValue("&lt;insert column name here&gt;") 一样读取它,或使用database.GetCollectino&lt;dynamic&gt; 您好,不是全部,而是部分。我已经创建了 C# 对象,并且大多数 feilds 似乎无一例外地反序列化,并且有时它可以正常工作,除了需要获取一些动态子对象。 【参考方案1】:

此属性会将字段名称从 mobj 映射到 csojo `[BsonElement(@"52WeekChange")]

【讨论】:

欢迎来到 SO。可以举个例子说明如何使用属性?【参考方案2】:

您有几个选项,正在探索here, in the docs。 (以下示例来自那里。)

您可以使用ClassMap

BsonClassMap.RegisterClassMap<MyClass>(cm => 
    cm.MapProperty(c => c.SomeProperty);
    cm.MapProperty(c => c.AnotherProperty);
);

如果你喜欢在你的 c# 类型声明中定义映射,你可以使用属性。

BsonContructor 可用于在对象构造期间映射属性:

public class Person

  public string FirstName  get; set; 
  public string LastName  get; set; 

  // You can use this on one or more overloads as well:
  [BsonConstructor]
  public Person(string firstName, string lastName)
  
    FirstName = firstName;
    LastName = lastName;
  

BsonElement 是属性级解决方案:

public class MyClass 
    // The first parameter ("sp") is an optional mongodb field name mapping.
    [BsonElement("sp")]
    public string SomeProperty  get; set; 

【讨论】:

以上是关于如何为方法 MongoDB.Bson.Serialization.BsonSerializer.Deserialize 自定义映射字段名称或类型的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Product* getProductFromID(std::string) 编写方法定义;

如何为 Gson 编组和解组创建通用方法?

如何为方法动态创建参数?

如何为 Swift 转换 MONActivityView 方法

如何为任意数量的变量运行一种方法[重复]

设计模式:如何为方法添加可选参数?