37

私は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 に同梱されているシリアライザーを使用するようにコントローラーのメソッドを変更すると、正常に動作します (ただし、これは日付が不格好になります)。

public JsonResult NiceJsonPlease()
    {

        var q = new TestClass();
        q.id = new ObjectId();
        q.test = "just updating this";

        return Json(q, JsonRequestBehavior.AllowGet);
    }
4

7 に答える 7

60

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; }
}
于 2013-05-29T20:17:05.200 に答える
29

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


}
于 2013-05-22T13:45:22.037 に答える
10

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

于 2014-01-06T15:14:06.677 に答える
2

私は Web 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
于 2014-06-25T19:26:53.180 に答える
1

別のオプションがあります

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);
于 2021-05-10T14:24:35.390 に答える