串行化Mongo ObjectId时出现JSON.NET错误

我正在玩MongoDB并且有一个带有mongodb ObjectId的对象。 当我使用.NET Json()方法将其序列化时,一切都很好(但日期太可怕了!)

如果我尝试使用JSON.NET序列化程序,它在尝试序列化ObjectID时会给我一个InvalidCastException

任何想法发生了什么以及如何解决这个问题?

using MongoDB.Driver; using MongoDB.Bson; using Newtonsoft.Json; //this is a route on a controller public string NiceJsonPlease() { var q = new TestClass(); q.id = new ObjectId(); q.test = "just updating this"; return JsonConvert.SerializeObject(q); } //simple test class class TestClass { public ObjectId id; //MongoDB ObjectID public string test = "hi there"; } Exception Details: System.InvalidCastException: Specified cast is not valid. 

如果您更改控制器方法以使用.NET附带的序列化程序,它可以正常工作(但是,这个给出了丑陋的日期,blugh)

 public JsonResult NiceJsonPlease() { var q = new TestClass(); q.id = new ObjectId(); q.test = "just updating this"; return Json(q, JsonRequestBehavior.AllowGet); } 

您可以使用.NET字符串类型而不是ObjectId,您只需要使用BsonRepresentation来装饰它。 如果您使用BsonDateTime,则会出现相同的转换问题。 这是我的项目中使用这些装饰器的域类。

 public class DocumentMetadata { [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } public string Name { get; set; } public string FullName { get; set; } [BsonDateTimeOptions(Kind = DateTimeKind.Utc)] public DateTime DownloadTime { get; set; } } 

我有一个来自MongoDB用户组的指针。 https://groups.google.com/forum/?fromgroups=#!topic/mongodb-csharp/A_DXHuPscnQ

响应是“这似乎是一个Json.NET问题,但不是真的。这里有一个自定义类型,它根本不知道。你需要告诉Json.NET如何序列化ObjectId。”

所以,我实现了以下解决方案

我装饰了我的ObjectId

 [JsonConverter(typeof(ObjectIdConverter))] 

然后编写了一个自定义转换器,它只是吐出ObjectId的Guid部分

  class ObjectIdConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value.ToString()); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override bool CanConvert(Type objectType) { return typeof(ObjectId).IsAssignableFrom(objectType); //return true; } } 

1)写ObjectId转换器

 public class ObjectIdConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(ObjectId); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.String) throw new Exception($"Unexpected token parsing ObjectId. Expected String, got {reader.TokenType}."); var value = (string)reader.Value; return string.IsNullOrEmpty(value) ? ObjectId.Empty : new ObjectId(value); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value is ObjectId) { var objectId = (ObjectId)value; writer.WriteValue(objectId != ObjectId.Empty ? objectId.ToString() : string.Empty); } else { throw new Exception("Expected ObjectId value."); } } } 

2)使用全局设置在全局JSON.NET中注册它,您不需要标记具有大属性的模型

  var _serializerSettings = new JsonSerializerSettings() { Converters = new List { new ObjectIdConverter() } }; 

我通过将JsonOutputMode设置为strict来解决了我遇到的与JSON.NET序列化程序/ InvalidCastException错误类似的问题,从根本上消除了更改基础类型的需要:

 var jsonWriterSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict }; var json = doc.ToJson(jsonWriterSettings); 

有关API的更多信息,请访问: http : //api.mongodb.org/csharp/1.8.3/html/d73bf108-d68c-e472-81af-36ac29ea08da.htm

我遇到了一个与Web API项目类似的问题,在我发现这个post之前,我已经在键盘上敲了几个小时。

最初一切都运行正常,但是在转换我的代码后使用我自己的自定义类而不是mongoDB C#驱动程序文档中建议的BsonDocument对象时遇到了问题。

http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-csharp-driver/#bsondocument-object-model-vs-your-own-domain-classes

这里的VB.net相当于上面那些需要它的解决方案;

 Public Class DocumentMetadata  _  _ Public Property Id() As String Public Property Name() As String Public Property FullName() As String  _ Public Property DownloadTime() As DateTime End Class 

我在VB.Net中使用了这个代码并且工作得很完美,你可以在类中看到objectId,你可以用数据类型DATE做同样的事情。

  Imports MongoDB.Bson Imports MongoDB.Bson.Serialization.Attributes Imports MongoDB.Driver Public Class _default Inherits System.Web.UI.Page Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim objMongo As New MongoClient("mongodb://192.168.111.5:27017") Dim objDatabase As IMongoDatabase = objMongo.GetDatabase("local") Dim objCollection = objDatabase.GetCollection(Of BsonDocument)("Test") Dim _ret As New List(Of mongo_users) Dim result = objCollection.Find(New BsonDocument()).ToList() Dim _json_response = result.ToJson() If _json_response <> "" Then _ret = MongoDB.Bson.Serialization.BsonSerializer.Deserialize(Of List(Of mongo_users))(_json_response) End If For Each item In _ret Response.Write(item.name & " " & item.last_name & "") Next End Sub End Class Public Class mongo_users   Public Property _id() As String Public Property status As Integer Public Property name As String Public Property last_name As String Public Property colors As List(Of user_colors) End Class Public Class user_colors Public Property color_name As String End Class