Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect serialization in C# using JSON.NET

I am attempting to take an object structured like so

public class Item
{
   public Guid SourceTypeID {get;set;}
   public Guid BrokerID {get;set;}
   public double Latitude {get;set;}
   public double Longitude {get;set;}
   public DateTime TimeStamp {get;set;}
   public object Payload {get;set;}
}

and serialize it with JSON.NET using a call like:

Item expected = new Item()
{
   SourceTypeID = Guid.NewGuid(),
   BrokerID = Guid.NewGuid(),
   Latitude = 33.657145,
   Longitude = -117.766684,
   TimeStamp = DateTime.Now,
   Payload = new byte[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
};
string jsonString = JsonConvert.SerializeObject(expected);

The payload member of the Item object will potentially hold any one primitive of a list of C# primitives (plus a few others like Guid), or an array of those types (as in the example, a byte array), or a "flat" object composed of any of those previously listed "primitives" (dynamically created).

When I perform the SerializeObject() call, the string that is produced contains:

{"Payload":"AAECAwQFBgcICQ==","SourceTypeID":"d8220a4b-75b1-4b7a-8112-b7bdae956a45",
 "BrokerID":"951663c4-924e-4c86-a57a-7ed737501dbd",
 "TimeStamp":"\/Date(1328202421559-0600)\/",
 "Latitude":33.657145,"Longitude":-117.766684}

However when I make the deserializing call the item that is produced is partially incorrect

Item actual = JsonConvert.DeserializeObject<Item>(jsonString);

actual.SourceTypeID : {00000000-0000-0000-0000-000000000000}
actual.BrokerID : {951663c4-924e-4c86-a57a-7ed737501dbd}
actual.Latitude : 33.657145;
actual.Longitude : -117.766684;
actual.TimeStamp : {2/2/2012 11:07:01 AM}
actual.Payload : null

The SourceTypeID member (Guid), and the Payload member (object, holding a byte[]), are both incorrect. The serialized string seems to hold the right identity for the guid, but not for the byte array.

I see that an alternate signatureof SerializeObject is

SerializeObject(object value, params JsonConverter[] converters);

Is this the correct way to inform the de/serialization engine about types that it apparently handles wrong? Since I am working with a limited set of "primitives" at the core of my object, if I could create a set of converters for each of those types, would that solve my problem?

I want to avoid reinventing the wheel if possible, as it seems that this would be a problem that has already been handled gracefully, and I'd like to leverage something like that if available.

like image 750
user1185689 Avatar asked Feb 02 '12 17:02

user1185689


2 Answers

Payload will be deserialized as a string unless you place a [JsonProperty] attribute with TypeNameHandling enabled on it, otherwise the deserializer won't know what to deserialize it as.

I haven't been able to duplicate the problem you got with some properties being null using the latest source code at http://json.codeplex.com/SourceControl/list/changesets

like image 195
James Newton-King Avatar answered Oct 11 '22 03:10

James Newton-King


This appears to be an actual bug in JSON.NET.

It's not idea, but a workaround might be to have a two-stage serialization. The first, the object that actually gets serialized to/from JSON, would consist only of fields/properties with string type. The second object (the one your server-side code would use) would be an object that is converted to strong types manually.

Not ideal, but possible. Additonally, you could consider using the DataContractJsonSerializer, which does a pretty good job of handling byte arrays and guids IME. Dates are still pretty sucky, but that's mostly the fault of Javascript.

like image 37
Randolpho Avatar answered Oct 11 '22 02:10

Randolpho