Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json.NET deserializing Mongo ObjectId is giving the wrong result

I'm using the official Mongo C# Driver, and RestSharp to call a Rest Api with Json.NET to perform my serialization/deserialization. Say I have a Person class as follows, which I'd like to POST & GET:

public class Person
{
  [JsonProperty("_id"),JsonConverter(typeof(ObjectIdConverter))]
  public ObjectId Id {get;set;}
  public string Name {get;set;}
}

I create a new Person object:

var person = new Person{Id = ObjectId.GenerateId(),Name='Joe Bloggs'};

POST it, and on the server I see the following which is correct:

{ _id: 52498b56904ee108c99fbe88, name: 'Joe Bloggs'}

The problem, is when I perform a GET the ObjectId I get on the client is {0000000000000...} i.e. not the {5249.....} I'd expect. The raw response is showing the correct value, but once I deserialize I loose it.

The ObjectIdConverter code is :

public 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)
   {
     var objectId = (ObjectId)existingValue; // at this point existingValue is {000...}
     return objectId;
   }

   public override bool CanConvert(Type objectType)
   {
     return (objectType == typeof (ObjectId));
   }
}

Any help would be appreciated.

like image 838
Click Ahead Avatar asked Sep 30 '13 15:09

Click Ahead


1 Answers

You are implementing the ReadJson method of the converter incorrectly. The existingValue parameter does not give you the deserialized value read from the JSON, it gives you the existing value of the object that you will be replacing. In most cases this will be null or empty. What you need to do is use the reader to get the value from the JSON, convert it as needed, then return the converted value.

Assuming your ObjectId class has a constructor that accepts a hex string, here is how you would implement the ReadJson method:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    JToken token = JToken.Load(reader);
    return new ObjectId(token.ToObject<string>());
}
like image 72
Brian Rogers Avatar answered Oct 12 '22 18:10

Brian Rogers