Kash Farooq's software development blog

.NET Developer

Creating .NET objects from JSON using DataContractJsonSerializer

Posted by Kash Farooq on January 31, 2011

Creating .NET objects from JSON using DataContract and DataMember

Note: .NET 4 has made it far easier to do this. See Creating objects from JSON in .NET 4.

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(string json) {
  var obj = Activator.CreateInstance();
  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(responseJson);
foreach (var googleSearchResult in results.ResponseData.Results) {
  Console.WriteLine(googleSearchResult.Url);
}

And for completeness, here is GetJsonDataFromGoogle():

public static string GetJsonDataFromGoogle(string searchTerm)
{
    var url = string.Format("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q={0}&rsz=large&start=0", searchTerm);
    var req = (HttpWebRequest) WebRequest.Create(url);
    req.Referer = "http://mywebsite.com";
    var res = (HttpWebResponse) req.GetResponse();
    string responseJson;
    using (var streamReader = new StreamReader(res.GetResponseStream())) {
        responseJson = streamReader.ReadToEnd();
    }
    return responseJson;
}
About these ads

10 Responses to “Creating .NET objects from JSON using DataContractJsonSerializer”

  1. Alex Lea said

    Hi Kash,

    Have you tried ReSTSharp? May not help in this case but the deserialisation is very good. Particularly good for xml where it just does ‘the right thing’ and you lose the ordering restrictions of DataContract. Not sure these apply to JSon mind ..

  2. In the Derserialise method, the following line:

    obj = (T) serializer.ReadObject(ms);

    needs to be changed to:

    obj = (T) serializer.ReadObject(memoryStream);

    Or else, rename the memoryStream variable to ms.

  3. Good post. I want to automatically create the .NET class based on the input string. I want to pass in a string with JSON and i want a tool which will autocreate the .NET class from the current JSON. Do you know a tool for that?

  4. Kirandeep said

    Hello,

    I’m trying to get some help understanding JSON deserialization when it comes to arrays and lists with a single object.

    I have a situation where a class, Employee, with properties like First, Last, and FavoriteCoffee, is always wrapped in an EmployeeList node, when I look at the XML (service provides xml and json).

    My problem has been that I have to read the string/stream from the service to find out if EmployeeList has a single Employee or multiple Employees. The JSON that I recieve has an array for multiple employees. I have to create an Employee class, an EmployeeList class, and a RootEmployee class:

    [DataContract]
    public class EmployeeList
    {
    [DataMember]
    public IList Employees {get; set;}
    }

    [DataContract]
    public class Employee
    {
    [DataMember]
    public string First {get; set;}

    [DataMember]
    public string Last {get; set;}

    [DataMember]
    public string FavoriteCoffee {get; set;}
    }

    [DataContract]
    public class EmployeeRoot
    {
    [DataMember]
    public string Employee Employee {get; set;}
    }

    These are the JSON strings I receive for a single record:

    {“Employee”:{“First”:”John”,”Last”:”Wayne”,”FavoriteCoffee”:”Maxwell”}}

    And for multiple records:

    {“Employee”:[{"First":"John","Last":"Wayne","FavoriteCoffee":"Maxwell"}, {"First":"Morgan","Last":"Freeman","FavoriteCoffee":"Choc Full O Nuts"}]}

    This is what I use to deserialize:

    private static T GetDataFromService(Uri uri)
    {
    T t = default(T);
    try
    {
    WebClient client = new WebClient();
    string analysisJson = client.DownloadString(uri);
    byte[] buffer = Encoding.Default.GetBytes(analysisJson);
    MemoryStream stream = new MemoryStream(buffer);

    stream.Position = 0;

    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(T));
    t = (T)jsonSerializer.ReadObject(stream);
    }…

    As I mentioned above, things work fine if I pass down an EmployeeRoot type when I know I’m going to receive a single Employee, and the EmployeeList when I know I’m receiving multiple records. However, when I don’t know, and I’ve passed down an EmployeeList, and only one record comes back, my EmployeeList does not get populated with a single Employee. Is there a better way to create my classes, or do I just have to look for a “[” in my JSON string to handle an EmployeeList with only one record (by deserializing into an EmployeeRoot object first and then somehow getting to the Employee object and adding it to List) ?

    Thanks.

  5. NA said

    Thanks a lot for this article, it help me a lot to create my .NET objects using a complex JSON stream containing hierachicals objects.

  6. Garnett Clarke said

    It would have been nice to see an implementation of GetJsonDataFromGoogle

  7. Problem with html format
    I think “Results” variable in the “ResponseData” class should be of IEnumerable(Result) type

    • Yep – thanks. Looks like WordPress stripped out my brackets.
      It should also be:
      IEnumerable Bracket Page EndBracket

      (Wordress is stripping my brackets from this comment too!)

      Now updated.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: