복붙노트

[MONGODB] 몽고 ObjectId가 직렬화 할 때 JSON.NET 오류 캐스팅

MONGODB

몽고 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);
    }

해결법

  1. ==============================

    1.대신 ObjectId가의 .NET 문자열 유형을 사용할 수 있습니다, 당신은 BsonRepresentation로 장식해야합니다. 당신이 BsonDateTime를 사용하는 경우, 동일한 변환 문제가됩니다. 이것은 그 장식을 사용하여 내 프로젝트의 도메인 클래스입니다.

    대신 ObjectId가의 .NET 문자열 유형을 사용할 수 있습니다, 당신은 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; }
    }
    
  2. ==============================

    2.나는 MongoDB의 사용자 그룹에서 포인터를했다. https://groups.google.com/forum/?fromgroups=#!topic/mongodb-csharp/A_DXHuPscnQ

    나는 MongoDB의 사용자 그룹에서 포인터를했다. https://groups.google.com/forum/?fromgroups=#!topic/mongodb-csharp/A_DXHuPscnQ

    응답이었다 "이것은 정말 Json.NET의 문제가 될 것 같다,하지만. 단순히 당신은 어떻게 ObjectId가를 직렬화하는 Json.NET을 알 필요가있다.에 대해 알고하지 않습니다 여기에 사용자 정의 유형이 있습니다."

    그래서, 나는 다음과 같은 솔루션을 구현

    나는 내 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;
        }
    
    
    }
    
  3. ==============================

    3.1) 쓰기 ObjectId가 계산기

    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<JsonConverter> { new ObjectIdConverter() }
                };
    

    3) 큰 조언 - 당신의 모델 ObjectId가를 사용하지 않는 - 사용 문자열

    [BsonRepresentation(BsonType.ObjectId]
    public string Id{ get;set; }
    
  4. ==============================

    4.나는 기본 유형을 변경 할 필요가 근절 엄격한에 JsonOutputMode을 설정하여 JSON.NET 시리얼 라이저 / InvalidCastException이 오류로 경험 한 비슷한 문제를 해결 :

    나는 기본 유형을 변경 할 필요가 근절 엄격한에 JsonOutputMode을 설정하여 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

  5. ==============================

    5.나는 웹 API 프로젝트와 비슷한 문제로 달리고, 나는이 스레드를 발견하기 전에 몇 시간 동안 키보드에 내 머리를 때리고 감아.

    나는 웹 API 프로젝트와 비슷한 문제로 달리고, 나는이 스레드를 발견하기 전에 몇 시간 동안 키보드에 내 머리를 때리고 감아.

    처음에는 모든 것이 잘 작동했지만, 그때는 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
        <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
    
  6. ==============================

    6.당신은 클래스의 OBJECTID을 볼 수 있습니다 당신은 데이터 유형 DATE과 같은 일을 할 수, VB.Net에서이 코드를 사용하고 완벽하게 일했다.

    당신은 클래스의 OBJECTID을 볼 수 있습니다 당신은 데이터 유형 DATE과 같은 일을 할 수, VB.Net에서이 코드를 사용하고 완벽하게 일했다.

        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
    
  7. from https://stackoverflow.com/questions/16651776/json-net-cast-error-when-serializing-mongo-objectid by cc-by-sa and MIT license