Creating .NET objects from JSON using DataContract and DataMember
In a previous post and demonstraed that the RESTful Google Search API returns data as JSON. I needed a way to convert the JSON data into .NET objects and this post shows what I ended up with.
Here is an example of the JSON result set returned:
{"responseData":
{"results":
[
{
"GsearchResultClass":"GwebSearch",
"unescapedUrl":"http://www.google.com/help/features.html",
"url":"http://www.google.com/help/features.html",
"visibleUrl":"www.google.com",
"cacheUrl":"http://www.google.com/search?q\u003dcache:BNRWhS8EKYAJ:www.google.com",
"title":"\u003cb\u003eSearch\u003c/b\u003e Features - \u003cb\u003eGoogle\u003c/b\u003e",
"titleNoFormatting":"Search Features - Google",
"content":"To find reviews and showtimes...."
},
{
"GsearchResultClass":"GwebSearch",
etc
},
etc
],
"cursor": {
"pages": [
{ "start": "0", "label": 1 },
{ "start": "8", "label": 2 },
etc
{ "start": "56","label": 8 }
],
"estimatedResultCount": "59600000",
"currentPageIndex": 0,
"moreResultsUrl": "http://www.google.com/search?oe=utf8&ie=utf8&source=uds&start=0&hl=en&q=MY SEARCH TEXT"
}
},
"responseDetails": null,
"responseStatus": 200
}
We can use System.Runtime.Serialization to create .NET objects from this JSON data.
For example, the top level JSON responseData can be represented by the following .NET type:
[DataContract]
public class GoogleSearchResults {
[DataMember(Name = "responseData")]
public ResponseData ResponseData { get; set; }
}
Note that I’ve specified the Name attribute. Without it I would have had to have a property called “responseData” rather than “ResponseData”.
The rest of the data is extracted using the classes below. Note that I can be quite selective in what data I wanted to transfer from JSON to .NET. If I don’t need, say, the “cacheUrl”, I can just omit it from my .NET objects. I can also rename data. I have put the data from “titleNoFormatting” into a property called Title:
[DataContract]
public class ResponseData
{
[DataMember(Name="results")]
public IEnumerable<Result> Results { get; set; }
[DataMember(Name = "cursor")]
public Cursor Cursor { get; set; }
}
[DataContract]
public class Cursor
{
[DataMember(Name = "moreResultsUrl")]
public string MoreResultsUrl { get; set; }
[DataMember(Name = "pages")]
public IEnumerable<Page> Pages { get; set; }
}
[DataContract]
public class Result
{
[DataMember(Name = "url")]
public string Url { get; set; }
[DataMember(Name = "titleNoFormatting")]
public string Title { get; set; }
}
[DataContract]
public class Page
{
[DataMember(Name = "start")]
public int Start { get; set; }
[DataMember(Name = "label")]
public string Label { get; set; }
}
Finally, I need a method to actually deserialize a JSON string into my .NET objects. I can use System.Runtime.Serialization.Json.DataContractJsonSerializer to do this. I have created the following generic method that takes a JSON string and the type I want it to be deserialised into, and then returns an instantiated .NET object:
public static T Deserialise<T>(string json) {
var obj = Activator.CreateInstance<T>();
using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json))) {
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = (T) serializer.ReadObject(memoryStream);
return obj;
}
}
This generic method can then be used to convert a JSON string to the specified .NET type:
string reponseJson=GetJsonDataFromGoogle("MY SEARCH TERM);
results = Deserialise<GoogleSearchResults>(responseJson);
foreach (var googleSearchResult in results.ResponseData.Results) {
Console.WriteLine(googleSearchResult.Url);
}