JSON.NET在序列化Mongo ObjectId时抛出错误



我正在玩MongoDB,并有一个MongoDB的ObjectId对象。当我用。net Json()方法序列化它时,一切都很好(但日期是可怕的!)

如果我尝试这个JSON。它给了我一个InvalidCastException当尝试序列化ObjectID

任何想法发生了什么,我怎么能解决这个问题?

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= !主题/mongodb-csharp A_DXHuPscnQ

反应为

这似乎是一个Json。NET问题,但不是真的。有一种习俗在这里输入,它根本不知道。你需要告诉Json。网如何序列化一个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转换器

    公共类ObjectIdConverter: JsonConverter{CanConvert(类型为objectType){返回objectType == typeof(objecd);}

     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<JsonConverter> { new ObjectIdConverter() }
             };
    
  3. 大建议-不要在你的模型中使用ObjectId -使用字符串

    [BsonRepresentation (BsonType.ObjectId)]公共字符串Id{获取;设置;}

我解决了JSON遇到的类似问题。. NET序列化器/InvalidCastException错误,通过将JsonOutputMode设置为strict,从而消除了更改底层类型的需要:

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项目中遇到了类似的问题,在我发现这个线程之前,我的头在键盘上敲了几个小时。

最初一切都很好,但后来我遇到了问题后转换我的代码使用我自己的自定义类而不是BsonDocument对象推荐在mongoDB c#驱动程序文档。

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

这里的VB.net等价于上面的解决方案,为那些需要它的人;

Public Class DocumentMetadata
    <BsonId> _
    <BsonRepresentation(BsonType.ObjectId)> _
    Public Property Id() As String
    Public Property Name() As String
    Public Property FullName() As String
    <BsonDateTimeOptions(Kind := DateTimeKind.Utc)> _
    Public Property DownloadTime() As DateTime
End Class

还有一个选项

object dotnetObject = BsonTypeMapper.MapToDotNetValue(bsonDocument);
// Json mapped to default .Net objects
string json = Newtonsoft.Json.JsonConvert.SerializeObject(dotnetObject);
// Parsing as JObject
var jobject = JObject.Parse(json);
// Deserializing as your custom Type
var myObject = JsonConvert.DeserializeObject<MyType>(json);

我在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 & "</br>")
        Next

    End Sub
End Class
Public Class mongo_users            
    <BsonId>
    <BsonRepresentation(BsonType.ObjectId)>
    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

相关内容

  • 没有找到相关文章

最新更新