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

Kee*_*eno 29 c# json.net mongodb

我正在玩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.
Run Code Online (Sandbox Code Playgroud)

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

public JsonResult NiceJsonPlease()
    {

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

        return Json(q, JsonRequestBehavior.AllowGet);
    }
Run Code Online (Sandbox Code Playgroud)

And*_*ndy 51

您可以使用.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; }
}
Run Code Online (Sandbox Code Playgroud)


Kee*_*eno 23

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

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

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

我装饰了我的ObjectId

[JsonConverter(typeof(ObjectIdConverter))]
Run Code Online (Sandbox Code Playgroud)

然后写了一个自定义转换器,只是吐出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;
    }


}
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说非常有效.我在这里找到了一个具有相同名称的类的完整版本:https://github.com/geersch/MySinglePageApplication/blob/master/MvcApplication/Models/ObjectIdConverter.cs (2认同)

ZOX*_*IVO 14

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.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

            var _serializerSettings = new JsonSerializerSettings()
            {
                Converters = new List<JsonConverter> { new ObjectIdConverter() }
            };
Run Code Online (Sandbox Code Playgroud)


小智 8

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

var jsonWriterSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict };
var json = doc.ToJson(jsonWriterSettings);
Run Code Online (Sandbox Code Playgroud)

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