Click here to Skip to main content
Click here to Skip to main content

Use C# to get JSON Data from the Web and Map it to .NET Class => Made Easy!

By , 30 Apr 2013
 

Introduction

This tip/trick demonstrates a complete and easy solution on how to get JSON formatted data from a web service, and map (deserialize) it to custom .NET class for further usage.

As an example, we will use http://openexchangerates.org site which provides latest currency rates formatted as JSON data. Latest daily rates will be retrieved from this here.

It outputs currency data in the following JSON format:

{
  "disclaimer": "This data is collected from various providers ...",
  "license": "Data collected from various providers with public-facing APIs ...",
  "timestamp": 1336741253,
  "base": "USD",
  "rates": {
    "AED": 3.6731,
    "AFN": 48.419998,
    "ALL": 107.949997,
    "AMD": 393.410004,
    "ANG": 1.79,
    "AOA": 94.949997,
    // ... more values ...
  }
} 

So, how do we retrieve them through C# on the server side and use them? Read on to find out.

How To - Three Easy Steps

Step 1. Install Json.Net library

Json.NET library provides an easy, and de-facto, standard way to convert (serialize) .NET class to JSON data, and JSON data back to .NET class (deserialize). 

The easiest way to install Json.Net library into your .NET project is via NuGet Package Manager Console by running this command:

install-package Newtonsoft.Json 

Alternatively, if you need to install it manually, download it from its project page on CodePlex.

Step 2. Create .NET class which will match JSON data format

If you are using Visual Studio 2012 you're in luck, since you can just paste a sample JSON data and it will create a class for you, To do that, first create a new class .cs file, select it in project explorer, than copy sample JSON data to clipboard, go to EDIT > Paste Special > Paste JSON as classes (thanks to Dave Kerr for this tip). More information on this feature here

If that won't work for you, or you'd prefer to do it yourself, you'll need to define .NET class manually. It must exactly match the format of JSON data provided to us by http://openexchangerates.org/latest.json:

public class CurrencyRates {
  public string Disclaimer { get; set; }
  public string License { get; set; }
  public int TimeStamp { get; set; }
  public string Base { get; set; }
  public Dictionary<string, decimal> Rates { get; set; }
} 

Note that property names are not case sensitive, but the name has to exactly match the JSON one. Also, notice how "rates" JSON property is matched to a Dictionary<string, decimal>. If "rates" would have a singular value, they could alternatively be matched to an Array or IEnumerable.

Step 3. Create a method to retrieve JSON data and map it to .NET class

Now we will create the following universal method that can be re-used for any .NET class, where 'T' represents any .NET class that you need JSON data to be mapped to:

using System.Net;
using Newtonsoft.Json;

// ...

private static T _download_serialized_json_data<T>(string url) where T : new() {
  using (var w = new WebClient()) {
    var json_data = string.Empty;
    // attempt to download JSON data as a string
    try {
      json_data = w.DownloadString(url);
    }
    catch (Exception) {}
    // if string with JSON data is not empty, deserialize it to class and return its instance 
    return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
  }
} 

Here, at first, an instance of WebClient() System.Net class (a part of the .NET) downloads data from the specific URL (http://openexchangerates.org/latest.json in our case) as a plain string.

Then, this string containing JSON data is mapped (deserialized) to any .NET class provided (CurrencyRates in our case).

Deserialization is done via Json.NET library's method JsonConvert.DeserializeObject<T>(json_data), which attempts to match all JSON fields to the same .NET class fields.

In this example, a call to a universal method _download_serialized_json_data<T>() can look like this:

var url = "http://openexchangerates.org/latest.json";
var currencyRates = _download_serialized_json_data<CurrencyRates>(url); 

And that's it! Now you can do anything you need with the data you retrieved.

Good luck!

History

  • 6/4/12 - Initial publication

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mikhail Tsennykh
Web Developer Nûby, Inc.
United States United States
Member
Namaste from Monroe, Louisiana!

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionMixed JSon to Objectmemberrhythmdivine7 Oct '12 - 3:27 
I have a class and correspoding JSon with the following structure in Silverlight 5.0:
 
JSon data:
[{"UserId":1,"LoginId":"abc","FirstName":"Rupak Kumar","LastName":"Das","Roles":[{"UserRoleId":1,"UserRoleName":"ReadOnly"},{"UserRoleId":2,"UserRoleName":"Edit"}]}]
 
Class definition:
public class Users
{
    #region Properties
    public int UserId { get; set; }
    public string LoginId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ObservableCollection<UserRoles> Roles { get; set; }
    #endregion
}
 
public class UserRoles
{
    #region Properties
    public int UserRoleId { get; set; }
    public string UserRoleName { get; set; }
    #endregion
}
 

I want to convert the JSon data directly to populate the object of Users.
Please help!!
rhythm divine..

AnswerRe: Mixed JSon to ObjectmemberMikhail Tsennykh7 Oct '12 - 7:05 
No problem! Smile | :)
 
Here you go:
using Newtonsoft.Json; // Json.Net library
using System.Collections.Generic;
using System.Collections.ObjectModel;
 
// ...

public List<Users> MapUsers() {
    var json_data = "[{\"UserId\":1,\"LoginId\":\"abc\",\"FirstName\":\"Rupak Kumar\",\"LastName\":\"Das\",\"Roles\":[{\"UserRoleId\":1,\"UserRoleName\":\"ReadOnly\"},{\"UserRoleId\":2,\"UserRoleName\":\"Edit\"}]}]";
 
    List<Users> users = JsonConvert.DeserializeObject<List<Users>>(json_data);
 
    return users;
}
This will return a list of you Json data mapped to your Users class. Just give it your source Json string instead of static variable, and you'll be good to go. I tested that in a sample project with the latest version of Json.Net library and it works great!
 
Good luck!
GeneralRe: Mixed JSon to Object [modified]memberrhythmdivine7 Oct '12 - 10:12 
When I am trying to user the snippet provided by you, it gives the below error:
Quote:
InvalidCastException: It is not possible to automatically convert a value of JSON type 'Array' to JSON type 'String'.
 
{System.InvalidCastException: It is not possible to automatically convert a value of JSON type 'Array' to JSON type 'String'.
at System.Json.JsonValue.CheckIfJsonType(JsonType valueType, JsonType targetType)
at System.Json.JsonValue.op_Implicit(JsonValue value)
at ExpenseTracker.ViewModels.LoginViewModel._ApiStub_GetUserDetailsServiceEvent(Object sender, CustomEventArgs`1 e)}

 
CustomEventArgs<object> => contains my jsondata as..
{[{"UserId":1,"LoginId":"abc","FirstName":"Rupak Kumar","LastName":"Das","Roles":[{"UserRoleId":1,"UserRoleName":"ReadOnly"},{"UserRoleId":2,"UserRoleName":"Edit"}]}]}
eJsonArray jsonData = (JsonArray)e.Value;
ObservableCollection<Users> users = JsonConvert.DeserializeObject<ObservableCollection<Users>>(jsonData);
 
So, I just converted the json data to string while passing to the DeserializeObject method. And BINGO!
 

 
BUT, I still have another small query and another observation. This method does not populate the values of static properties (I removed the static keyword and it populates the value). And also, what if, the properties that I am populating belong to a static class. For now, I am directly accessing the Values against the Keys for populating the static properties of the static class.
 
Kindly provide a logic to overcome the same or let me know if this is a limitation.
rhythm divine..


modified 7 Oct '12 - 16:34.

GeneralRe: Mixed JSon to ObjectmemberMikhail Tsennykh9 Oct '12 - 11:14 
Great, that you got it at least partially working. Since I never worked with Silverlight, I might nto be able to help you with its specifics. We'll see.
 
As for not being able to map JSON to static class, this is not really a limitation. Static classes with static properties are designed to be used in a particular manner:
var variable = StaticClass.StaticProperty();
Static classes cannot be inherited or have an interface, be a part of a list or collection, etc. Their main purpose is to be called directly or as an extensions of another classes.
 
On the other hand non-static classes can have interfaces and be inherited, and inherit from. They provide more flexibility that static ones.
 
Both types have their own place in C# (.NET) ecosystem where particular usage is enforced.
 
To work with data retrieved from JSON you shouldn't need to use static class (unless it is a specific requirment of Silverlight, which again I am not familiar with).
 
If you really need to use static class, you'll most probably have to map your dynamic class by manually:
// Your user in a non-static class
var user = new User { /* user data */ };
 
// Map by hand to static class
YourStaticUsersClass.UserId = user.UserId;
YourStaticUsersClass.LoginId = user.LoginId;
YourStaticUsersClass.FirstName = user.FirstName;
// ... and similarly for all the properties ...
Once again you shouldn't be needing to explicitly use static class or properties, unless it is some requirement of Silverlight.
 
How is data retrieved from JSON should be used in your application? Can you give any sample code of how or where it is intended to be used?
GeneralMy vote of 5membermanoj kumar choubey18 Jul '12 - 20:49 
Nice
QuestionWhy ? DataContractJsonSerializer works fine.memberNicolas Dorier6 Jun '12 - 4:01 
DataContractJsonSerializer[^] is shipped with .NET, compatible with WCF, and do already that for you.
AnswerRe: Why ? DataContractJsonSerializer works fine.memberMikhail Tsennykh6 Jun '12 - 6:37 
Thumbs Up | :thumbsup: Great question!
 
For starters, I only work with MVC framework web applications, and honestly, I have very little idea about WCF programming))
 
After looking at samples of DataContractJsonSerializer in this example: http://msdn.microsoft.com/en-us/library/bb410770.aspx[^], It looks like DataContractJsonSerializer might be better suited for WCF applications, since it works directly with MemoryStream, which is rarely needed in web application.
 
Also, to serialize a class to Json in DataContractJsonSerializer looks like this:
MemoryStream stream1 = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(CurrencyRates));
ser.WriteObject(stream1, currencyRates)
And to deserialize:
CurrencyRates currencyRates = (CurrencyRates)ser.ReadObject(stream1);
According to this reference[^] it can read only Stream and XmlReader, which might need further conversions from other data types.
 
The other thing about Json.Net - most operations can be done in one line.
Serialize:
string json = JsonConvert.SerializeObject(currencyRates);
Deserialize:
CurrencyRates currencyRates = JsonConvert.DeserializeObject<CurrencyRates>(json);
So code is cleaner, more readable, and easier to use.
 
Also, main reason for me to prefer Json.Net, is that it will be shipped as a part of Microsoft MVC 4 framework[^], which alone is a sign of recognition of Json.Net as a good alternative for serialization needs, at least on the web application development front.
 
And finally, Json.Net is supposed to be much faster than DataContractJsonSerializer according to performance comparison here: http://james.newtonking.com/pages/json-net.aspx[^], which is good for web applications, where speed is crucial.
 
In addition, here - http://stackoverflow.com/questions/4826742/json-net-vs-datacontractjsonserializer[^] is some interesting comparison of Json.Net and DataContractJsonSerializer.
 
What do you think?
GeneralRe: Why ? DataContractJsonSerializer works fine.memberNicolas Dorier6 Jun '12 - 7:14 
Thanks for the links, interesting.
 
Anyway, for the readability stuff, an extension or helper method and you are ready to read from a string.
 
Good point for the rest.
GeneralMy vote of 5memberOthello744 Jun '12 - 21:40 
Short and to the point. Good stuff. Smile | :)
GeneralRe: My vote of 5memberMikhail Tsennykh5 Jun '12 - 6:17 
Thank you! Smile | :)

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 30 Apr 2013
Article Copyright 2012 by Mikhail Tsennykh
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid