Just a quick heads up for working with JSON on Windows 8.
If you have worked with JSON on Windows Phone 7, you are most likely very familiar with the DataContractJsonSerializer class. When working with JSON, using DataContractJsonSerializer is the most common approach I see. The approach typically looks something like this.
First, you define a class that will contain the parsed JSON data. You mark with class up with [DataContract] and [DataMember] attributes. If I was getting data from Twitter, it might look something like this:
[DataContract]
public class Tweet
{
[DataMember("text")]
public string Text {get;set)
[DataMember("profile_image_url")]
public string ImageUrl{get;set)
[DataMember("from_user_name")]
public string Poster{get;set)
}
While straightforward, it is a bit cumbersome. You have to create class. You then may want to map the property names from Twitter to different property names in your .NET class. It gets even more complicated if the JSON has properties that contain other JSON objects. Now you have to create additional classes to parse those results.
Once you have your classes created, you would then parse the JSON as shown:
var jsonSerializer = new DataContractJsonSerializer(typeof(Tweet));
var results = jsonSerialzer.ReadObject(someStream) as Tweet;
The above is closer to pseudo code than real code, but the one thing to point out is that the ReadObject method requires an input stream that provides the JSON. If you are working with a string of JSON, you have to put it into a MemoryStream and then parse it. The extra step can be annoying.
JSON in Windows 8 – A Simpler Approach
In Windows 8, we have the JsonObject class that makes life simpler when working with JSON. The JsonObject has existed in “regular” Silverlight for sometime, but never made an appearance on Windows Phone. It has undergone some changes on Windows 8, giving us some new methods to work with. For quick and dirty JSON processing, the JsonObject works pretty well. If you have more complex needs, you may want to checkout the JSON.Net library.
With the JsonObject, we can parse are JSON like this:
var json = JsonObject.Parse(jsonString);
Things don’t get much easier than that. I can access properties on the parsed results with just as easily:
var prop = json.GetNamedString(“someProperty”);
There are other methods like GetNamedBoolean, GetNamedObject, and GetNamedArray. Let’s take a look at GetNamedArray, in particular, since I think it will be used frequently.
If you take a look at this Twitter search, you will see that the actual results of the search are contained in an array of JSON objects called “results”. This is a pretty common occurrence in the world of JSON.
Handling it with JsonObject is pretty straightforward once you get the hang of it. If I wanted to databind the results of that search to a list of tweet results, I could do something like this:
var results = json.GetNamedArray("results");
var tweets = from r in results
select new { text = r.GetObject().GetNamedString("text"),
image = r.GetObject().GetNamedString("profile_image_url"),
poster = r.GetObject().GetNamedString("from_user_name") };
The “tricky” part is that the values stored in a call to GetNamedArray are not JSON objects, even though we know the results property contains JSON objects. The returned array is actually a list of JsonValue’s because it is possible that we are dealing with an array of strings, for example. As a result, when iterating through the results, we need to make a call to GetObject on each item in the list.
Obviously, not a lot of error checking going on, but it does a fine job illustrating the core concepts. If you are interested in how this would be used in an application, here is an example method that calls the Twitter search reference above:
private async void SomeMethod()
{
var http = new HttpClient();
http.MaxResponseContentBufferSize = Int32.MaxValue;
var response = await http.GetStringAsync("");
var json = JsonObject.Parse(response);
var results = json.GetNamedArray("results");
var tweets = from r in results
select new {
text = r.GetObject().GetNamedString("text"),
image = r.GetObject().GetNamedString("profile_image_url"),
poster = r.GetObject().GetNamedString("from_user_name") };
}