Parsing Json with MonoTouch and MonoTouch.Dialog
April 14, 2011
When i first started building the SideBox iPhone app, I tried to parse Json using native .net api’s. I failed. Why? Well mostly because I did not know what I was doing, but also because I was under a pinch to bang it out quickly. Back then I decided to go with a port of the JSON.NET library called Newtonsoft.Json. It has worked well for me up until recently. I began processing some nested json with weird arrays and such and my Json parsing started breaking down. Probably my fault, but I again was in a pinch and needed to bang out a quick solution.
I knew that the MonoTouch.Dialog app named TweetStation was using System.Json so I took a peak at that source code and it turns out things have gotten really simple in .net for parsing. Here is an example of how I’m using System.Json to parse Json coming back from an HttpWebResponse, and creating an iPhone UI with a list of StackOverflow questions that lets you drill-down to the question’s set of tags:
I’m using the StackExchange StackAppsAPI to fetch questions tagged with MonoTouch. Here is the entire source code to render this iPhone UI:
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Json; | |
using System.Net; | |
using MonoTouch.Dialog; | |
using MonoTouch.Foundation; | |
using MonoTouch.UIKit; | |
namespace MonoTouch.Dialog.JsonExample | |
{ | |
public class Application | |
{ | |
static void Main (string[] args) | |
{ | |
UIApplication.Main (args); | |
} | |
} | |
// The name AppDelegate is referenced in the MainWindow.xib file. | |
public partial class AppDelegate : UIApplicationDelegate | |
{ | |
RootElement rootElement; | |
// This method is invoked when the application has loaded its UI and its ready to run | |
public override bool FinishedLaunching (UIApplication app, NSDictionary options) | |
{ | |
window.AddSubview (navigationController.View); | |
window.MakeKeyAndVisible (); | |
var root = CreateRoot (GetStackOverflowQuestions ()); | |
var dv = new DialogViewController (root, true); | |
navigationController.PushViewController (dv, true); | |
return true; | |
} | |
// This method is required in iPhoneOS 3.0 | |
public override void OnActivated (UIApplication application) | |
{ | |
} | |
RootElement CreateRoot (List<Question> questions) { | |
var section = new Section (); | |
rootElement = new RootElement ("StackOverflow Questions") { section }; | |
foreach (var question in questions) { | |
var questionRow = new RootElement (question.title); | |
foreach (var tag in question.tags) { | |
questionRow.Add( new Section (tag)); | |
} | |
section.Add (questionRow); | |
} | |
return rootElement; | |
} | |
//Don't forget to gzip decompress: http://stackapps.com/questions/907/strange-encoding-for-json-output | http://stackoverflow.com/questions/4567313/uncompressing-gzip-response-from-webclient | |
List<Question> GetStackOverflowQuestions () { | |
var request = (HttpWebRequest) WebRequest.Create ("http://api.stackoverflow.com/1.1/search?tagged=monotouch"); | |
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; | |
using (var response = (HttpWebResponse) request.GetResponse ()) { | |
using (var streamReader = new StreamReader (response.GetResponseStream ())) { | |
JsonValue root = JsonValue.Load (streamReader); | |
List<Question> questions = ParseJsonAndLoadQuestions ( (JsonObject) root); | |
return questions; | |
} | |
} | |
} | |
public List<Question> ParseJsonAndLoadQuestions (JsonObject json) { | |
var questions = new List<Question> (); | |
var questionJson = json["questions"]; | |
foreach (JsonObject jentry in questionJson) { | |
questions.Add(new Question() { | |
question_id = jentry["question_id"].ToString(), | |
tags = ParseAndLoadTags ((JsonArray) jentry["tags"] ), | |
title = jentry["title"].ToString() | |
}); | |
} | |
return questions; | |
} | |
public List<string> ParseAndLoadTags (JsonArray json) { | |
var tags = new List<string> (); | |
foreach (var tag in json) { | |
tags.Add (tag); | |
} | |
return tags; | |
} | |
public class Question { | |
public string question_id { get; set; } | |
public string title { get; set; } | |
public List<string> tags { get; set; } | |
} | |
} | |
} |