JSON.NET erreur de moulage lors de la sérialisation de Mongo ObjectId
je joue avec MongoDB et j'ai un objet avec un objet mongodb dessus. Quand je sérialise ceci avec la méthode .NET Json (), tout est bon (mais les dates sont horribles!)
si j'essaie ceci avec le JSON.NET serialiser il me donne une InvalidCastException en essayant de sérialiser L'ObjectID
des idées sur ce qui se passe et comment je peux arranger ça?
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.
si vous changez la méthode du contrôleur pour utiliser le sérialiseur qui est livré avec .NET, il fonctionne bien (mais, celui-ci donne laid dates, blugh)
public JsonResult NiceJsonPlease()
{
var q = new TestClass();
q.id = new ObjectId();
q.test = "just updating this";
return Json(q, JsonRequestBehavior.AllowGet);
}
6 réponses
Vous pouvez utiliser le type de chaîne de caractères .NET au lieu de ObjectId, vous avez juste besoin de le décorer avec BSON representation. Si vous utilisez BsonDateTime, vous aurez le même problème de conversion. C'est un domaine classe dans mon projet qui utilise ces décorateurs.
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; }
}
j'avais un pointeur du groupe D'utilisateurs MongoDB. https://groups.google.com/forum/?fromgroups=#!topic/mongodb-csharp/A_DXHuPscnQ
La réponse a été "Cela semble être Json.NET question, mais pas vraiment. Il y a un type personnalisé ici il ne sait tout simplement pas. Tu dois le dire Json.NET comment sérialiser un ObjectId."
ainsi, j'ai implémenté la solution suivante
j'ai décoré mon ObjectId
[JsonConverter(typeof(ObjectIdConverter))]
Ensuite écrit un le convertisseur personnalisé qui crache juste sur la portion Guid de L'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) Écrire ObjectId convertisseur
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.");
}
}
}
var _serializerSettings = new JsonSerializerSettings()
{
Converters = new List<JsonConverter> { new ObjectIdConverter() }
};
j'ai résolu un problème similaire, j'ai été rencontré avec le JSON.NET sérialiseur/InvalidCastException erreur en définissant le JsonOutputMode strictes, qui a éliminé la nécessité de changer le type sous-jacent:
var jsonWriterSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.Strict };
var json = doc.ToJson(jsonWriterSettings);
avec d'autres informations disponibles dans L'API: http://api.mongodb.org/csharp/1.8.3/html/d73bf108-d68c-e472-81af-36ac29ea08da.htm
j'ai rencontré un problème similaire avec un projet D'API Web, et j'ai fini par frapper ma tête contre le clavier pendant quelques heures avant de trouver ce fil.
Au début, tout fonctionnait bien, mais ensuite j'ai rencontré le problème après avoir converti mon code pour utiliser ma propre classe personnalisée au lieu de L'objet BsonDocument comme recommandé dans le pilote mongoDB C#. documentation.
Ici VB.net équivalent à la solution ci-dessus pour ceux qui en ont besoin;
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
j'ai utilisé ce code dans VB.Net et travaillé parfait, vous pouvez voir l'objectId dans la classe et vous pouvez faire la même chose avec le type de données 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