I don’t work with JSON every day. In fact, I hadn’t used it at all until the beginning of this year, when I made REST calls to Twitter and retrieved gobs of tweets as JSON.
I’m now working on a project that contains collections of immutable C# objects, and those objects need to make their way to ActionScript. Given that ActionScript is based on ECMAScript, it seems appropriate to serialize these objects as JSON so that ActionScript might easily consume them.
During my Twitter tinkering, I was using an older version of the .NET runtime, and I had no other choice but to rely on third party libraries for JSON support, lest I roll my own. This time, I have the latest and greatest at my fingertips, and I decided to take it for a test drive.
It’s simple, and perfectly innocent. Deserializing, however, proved to be slightly more difficult.
This would have worked, but the Deserialize() method depends on the existence of a default constructor, and invokes each property setter individually. That’s fine if you’re working with mutable objects, but for concurrency concerns, I insisted my objects be immutable.
The overload of
Serialize() produced the same results.
DeserializeObject() returned a dictionary of objects keyed by string. I added a constructor to MyObject specifically to consume it. This worked, but I wasn’t pleased with having to add a separate constructor, and I wondered what I might do if types didn’t match up properly.
I continued to capture my assumptions as unit tests, and everything seemed to be working decently … until I hit a DateTime object. I would serialize a DateTime, and it would deserialize as a DateTime four hours ahead. Something was clearly awry.
I’ve used Json.NET in the past, and so with confidence, I fired up NuGet, downloaded Json.NET, and within the span of about five minutes, was able to produce this:
var jsonText = JsonConvert.SerializeObject(myObj); var deserializedObj = JsonConvert.DeserializeObject<MyObject>(jsonText);
And, voila! Notice how I’m providing the type? Json.NET is intelligent enough to invoke my constructor with the proper values rather than just relying on a default constructor and invoking each property.