MissingMember handling with mismatched JSON

Oct 3, 2009 at 5:47 PM

Based on JsonSerializerSettings, we can have behavior where a missing member (found in JSON but on on the destination Type) causes an exception, or is ignored. The TweetSharp project currently uses exception behavior, because we use multiple extension methods that attempt to convert a Twitter response to data classes. In our serialization logic, we catch the exception and return null back to let the caller know that the JSON provided is not meant to be the Type they wanted it to be:

string response = (web call to http://twitter.com/statuses/public_timeline.json);

// This would return null; the response is a collection of statuses, not a user
TwitterUser user = response.AsUser();

Now, the big flaw with this approach is that Twitter routinely adds new features in the form of properties to their API, so our deserialization calls fail because we throw an Exception when the response shows up with a feature we didn't know about. That means all 2000 Twitter applications and clients currently running TweetSharp break fatally until we update our object model and send out a new build.

So, the logical next step is to switch off exceptions when missing members are encountered. The problem with this approach is that if the JSON response is completely different (i.e. not the intended type at all) we still end up with an empty activator-based instance of the requested type:

string response = (web call to http://twitter.com/statuses/public_timeline.json);

// This should return null but it returns a completely null TwitterUser instance
TwitterUser user = response.AsUser();

This doesn't work because it masks errors from twitter (which can be deserialized with AsError) and there's no safe way to determine the object coming out of the deserializer is supposed to what it is, or if it's a zombie based on mismatched JSON. We could engage a bunch of Regex rules to get a sense of what's coming back but it would be much cleaner if we can accomplish this at the JsonSerializer level.

 

 

Coordinator
Oct 3, 2009 at 11:53 PM

You could get what you want by leaving MissingMemberHandling to Ignore and setting Required=true on [JsonProperty]

Oct 4, 2009 at 4:43 PM

Almost; I can use IsRequired to guarantee values, but I was hoping to guarantee structure only. In other words, I can't find a way to use IsRequired and have the serializer not throw an exception if the required property value happens to be null (which is allowed), I only care that the property is in the JSON message to distinguish model classes with similar properties from each other. I tried changing DefaultValueHandling and NullValueHandling parameters to Include.

Coordinator
Oct 5, 2009 at 9:29 AM

I took a look at how WCF treats IsRequired and its serializer accepts null elements. I've changed Json.NET to match. IsRequired should do what you're looking for now.

Source code is in CodePlex.