Consuming JSON data in WinRT

Following the session that Glenn (twitter) and I presented at Community Day 2012 as members of the Belgian Windows Phone User Group, we’re writing a couple of posts explaining the topics and showing some code. The topic of today is consuming JSON in WinRT apps.

Before WinRT you could use the WebClient class to access your JSON APIs, but this class isn’t available for Windows 8 Metro applications. For these kind of applications you’ll have to use the new HttpClient class in combination with the async/await keywoards for asynchronous web access. The GetAsync() methods returns a HttpResponseMessage containing the returned status code, response headers and content.

public async Task<string> GetJsonString()
{
    HttpClient client = new HttpClient();
    string url = "http://urltoyourApi";
    HttpResponseMessage response = await client.GetAsync(url);
    return response.Content.ReadAsString();
}

In case you need extra tinkering of your web requests or responses, you can inject your own MessageProcessingHandler in the HttpClient, although this shouldn’t be needed for most scenarios.

HttpMessageHandler handler = new HttpClientHandler();
handler = new MyMessageProcessingHandler(handler);
var HttpClient = new HttpClient(handler);
HttpClient.BaseAddress = serviceUri;
HttpClient.MaxResponseContentBufferSize = 100000;
/// <summary>
/// In case you need to customize request/response
/// </summary>
public class MyMessageProcessingHandler : MessageProcessingHandler
{
    public MyMessageProcessingHandler(HttpMessageHandler innerHandler)
        : base(innerHandler)
    {
    }

    // Process the request before sending it
    protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request,
         CancellationToken cancellationToken)
    {
        if (request.Method == HttpMethod.Get)
        {
            request.Headers.Add("Custom-Header", "CustomRequestValue");
        }
        return request;
    }

    // Process the response before returning it to the user
    protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response,
         CancellationToken cancellationToken)
    {
        if (response.RequestMessage.Method == HttpMethod.Get)
        {
            response.Headers.Add("Custom-Header", "CustomResponseValue");
        }
        return response;
    }
}

Parsing the JSON string

For the second part of your job, parsing the JSON string into an object, there is another new class available in .NET 4.5: JsonObject. You can feed the returned string into this class by using the constructor or the Parse() method. An exception will be thrown if the JSON string is invalid and can’t be parsed correctly. Once the parsing is done, the JsonObject behaves like a sort of dictionary from which you can get values by string indexers or methods.

public async void DoSomeParsing()
{
    string responseText = await GetJsonString();
    JsonObject root = new JsonObject(responseText);

    // parse properties
    bool isSuccess = root.GetNamedString("status") == "ok"; // get string
    string type = root["type"].GetString(); // get string with indexer
    int size = (int)root.GetNamedNumber("size"); // get int
    JsonObject subObject = root.GetNamedObject("someSubObject"); // get another json object
}

This approach is fine if you need only a few properties out of your JSON tree, but can get quite cumbersome for large trees plus you don’t have any IntelliSense available for all the property names. You can still fall back on the DataContractJsonSerializer, which is moved to the System.Runtime.Serialization assembly. You will also have to define the correct classes to be able to deserialize, but there are tools like json2csharp available to help you with that part. The deserialized result is a nice C# object tree.

public async void DoSomeDeserializing()
{
    string responseText = await GetJsonString();

    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(MyRootObject));
    using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(responseText)))
    {
        var rootObject = serializer.ReadObject(stream) as MyRootObject;
    }
}

But my favorite library for JSON manipulations is still JSON.NET. This library allows you to serialize and deserialize with a single line of code, directly to the objects you defined. You can again use json2csharp to create your model, if you don’t have it available yet. Since our API for the Community Day demo was uniform for all types, I provided both a generic method that retrieves a single item and one that returns a collection of items.

public async Task<T> GetItem(string someUri)
{
    T resultItem = new T();

    HttpResponseMessage response = await HttpClient.GetAsync(someUri);
    if (response.StatusCode == HttpStatusCode.OK)
    {
        string responseString = await response.Content.ReadAsStringAsync();
        // parse to json
        resultItem = JsonConvert.DeserializeObject<T>(responseString);
    }
    else
    {
        throw new Exception(response.StatusCode.ToString() + " " + response.ReasonPhrase);
    }

    return resultItem;
}

Up to you which of the 3 possibilities you pick for your implementation, good luck !

Licensed under CC BY-NC-SA 4.0; code samples licensed under MIT.
comments powered by Disqus
Built with Hugo - Based on Theme Stack designed by Jimmy