Ошибка при запуске JSON.NET при сериализации Mongo ObjectId

Я играю с MongoDB и имею объект с объектом mindodb ObjectId. Когда я сериализую это с помощью метода .NET Json (), все хорошо (но даты ужасны!)

Если я попробую это с сериализатором JSON.NET, это даст мне 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. 

Если вы измените метод controllerа для использования сериализатора, который поставляется с .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, у вас будет такая же проблема с конверсией. Это class домена в моем проекте, который использует эти декораторы.

 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))] 

Затем написал пользовательский конвертер, который просто выплескивает часть Guid объекта ObjectId

  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() } }; 

Я разрешил аналогичную проблему, с которой я столкнулся с ошибкой serializer / InvalidCastException JSON.NET, установив строгую процедуру JsonOutputMode, которая устранила необходимость изменения базового типа:

 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

У меня возникла аналогичная проблема с проектом веб-API, и я потерял голову над клавиатурой в течение нескольких часов, прежде чем нашел этот stream.

Первоначально все работало нормально, но затем я столкнулся с проблемой после преобразования моего кода, чтобы использовать свой собственный пользовательский class вместо объекта 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  _  _ 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 в classе, и вы можете сделать то же самое с типом данных 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 
  • mongodb / mongoose findMany - найти все документы с идентификаторами, перечисленными в массиве
  • Почему рекомендуется не закрывать соединение MongoDB нигде в коде Node.js?
  • Лучшая практика для поддержания сеанса mgo
  • Как удалить дубликаты на основе ключа в Mongodb?
  • Групповая агрегация Mongodb $ group, ограничить длину массива
  • получение атрибутов схемы из модели Mongoose
  • MongoDB Aggregation: Как получить общее количество записей?
  • Текстовый поиск MongoDB и несколько поисковых слов
  • В чем разница между findAndModify и обновлением в MongoDB?
  • Обновить поле в массиве точного элемента в MongoDB
  • MongoDB 'count ()' очень медленный. Как мы усовершенствуем / работаем с ним?
  • Interesting Posts

    Как проверить, есть ли у меня доступ к Sudo?

    Почему WordPress помещает «text / rocketscript» вместо «text / javascript» при использовании wp_register_script ()?

    Как устранить ошибку «Отсутствие спецификации материалов» при обновлении OSX 10.3 до 10.5?

    Правильное переключение между HTTP и HTTPS с использованием .htaccess

    Как преобразовать int в байт

    Google Map Android API v2 не может отображать карту в приложении магазина воспроизведения

    iphone sdk – удалить все символы, кроме цифр 0-9, из строки

    Nginx и Ubuntu в Windows

    Как получить необработанные данные предварительного просмотра из объекта Camera не менее 15 кадров в секунду в Android?

    Питание на ноутбуке без крышки

    Как избежать исключения ArrayIndexOutOfBoundsException или IndexOutOfBoundsException?

    отображение AM и PM в маленькой букве после форматирования даты

    Как выпустить указатель из boost :: shared_ptr?

    Когда следует использовать Html.Displayfor в MVC

    Box Shadow в строке таблицы, не отображающейся в некоторых браузерах

    Давайте будем гением компьютера.