1. MongoDB .Net Driver#

不禁好奇为什么当存储对象到 mongodb 序列化为 BSON 或者 序列化为 json 时, 如果字段上有一些注解, 他们就会自动被对应的序列化框架识别, 这是怎么实现的呢:

using MongoDB.Bson;
using Newtonsoft.Json;

public class MessageModel
{
    // MongoDB .Net Driver 相关注解
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }
  
    // JSON 注解
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime CreateTime { get; set; } = DateTime.Now;
}

1.1. MongoDB 注解#

  • 反射(Reflection):MongoDB .Net Driver 在序列化或反序列化对象时,会通过反射检查类的结构,识别是否有特定的属性(如 [BsonId][BsonRepresentation]
  • 序列化器(Serializer):MongoDB .Net Driver 内置了一套序列化器(IBsonSerializer),它们会根据注解动态调整序列化行为
    • [BsonId]:标记某个字段为主键(MongoDB 中的 _id 字段),驱动会确保这个字段被正确映射到 _id
    • [BsonRepresentation(BsonType.ObjectId)]:指定字段在 MongoDB 中存储为 ObjectId 类型,而不是普通的字符串

具体流程:

  1. 创建一个 MessageModel 实例
  2. 当你调用 MongoDB 驱动的插入方法(如 collection.InsertOneAsync(model)
  3. 驱动通过反射读取 MessageModel 类的元数据,发现 Id 字段有 [BsonId][BsonRepresentation(BsonType.ObjectId)]
  4. 驱动将 Id 字段映射为 MongoDB 文档的 _id 字段,并确保其值符合 ObjectId 格式
  5. 其他字段(如 CreateTime)也会根据默认或自定义的序列化规则转换为 BSON 格式

1.2. JSON 注解#

反射(Reflection):Json.NET 在序列化或反序列化对象时,会通过反射检查类的属性,查找是否有 [JsonConverter] 等注解

自定义转换器(JsonConverter)[JsonConverter(typeof(CustomDateTimeConverter))] 告诉 Json.NET 在序列化 CreateTime 字段时,使用 CustomDateTimeConverter 类来控制输出格式(例如,格式化日期时间为特定的字符串格式)

2. Json.NET (Newtonsoft.Json)#

非常流行的开源 .NET 库,用于处理 JSON 数据,它在 .NET 社区中广为人知,因此很多人直接称它为 Json.NET,而不是完整的命名空间 Newtonsoft.Json,它提供了一组类和方法,用于:

  • 序列化:将 C# 对象转换为 JSON 字符串
  • 反序列化:将 JSON 字符串转换回 C# 对象
  • 自定义序列化:通过特性(如 [JsonConverter] 注解)或配置,允许开发者控制 JSON 的格式和行为
var person = new { Name = "Alice", Age = 30 };
string json = JsonConvert.SerializeObject(person);
// 输出: {"Name":"Alice","Age":30}

string json = "{\"Name\":\"Alice\",\"Age\":30}";
var person = JsonConvert.DeserializeObject<dynamic>(json);
// person.Name == "Alice"

JsonConvertNewtonsoft.Json 命名空间中的一个静态类,属于 Json.NET 库