The web is packed full of web APIs just waiting to be consumed. Sites such as Meetup, GitHub, Twitter, LinkedIn, and Facebook to name a few all have developer APIs that can be used programmatically to consume the data contained within their site. By implementing their APIs in similar fashions using REST, JSON, and OAuth, the ease at which these APIs can be consumed is amazing.
For this post, I am going to discuss how to consume GitHub’s RESTful web API using web resources, NuGet packages, the .NET framework, and a few lines of C# code.
The first thing that should always be done is to seek out documentation for the web API. The current version for GitHub’s is v3 and can be found here. By looking at the documentation, you will notice that the first page discusses topics such as Schema, Client Errors, HTTP Verbs, Authentication, Pagination, Rate Limiting, and a few others. While all are equally important, we will be focusing on Schema and later on Authentication.
All API access is over HTTPS, and accessed from the
api.github.com domain. All data is sent and received as JSON.
1 2 3 4 5 6 7 8 9 10 11 12 13
Blank fields are included as
null instead of being omitted.
All timestamps are returned in ISO 8601 format:
So what exactly does all this mean? The schema provides the information needed to know where and how to get the data along with how to process the data once you have it. In our case the schema defines that all API access is over HTTPS and can be accessed from the domain
The rest of the information shown has an example request to the API using curl and discusses two important points on the data. The first states that blank fields are included as null. This is very important because it makes it even easier for discovering the data returned by the API without having to refer to the documentation. Any call to the API will return all possible fields even if they are null. The second item describes the format for timestamps so that they can be processed properly.
Now that we know where to access the API and the type of data to expect, we can make our first call. Fire up your preferred web browser and navigate to the following location https://api.github.com/users/scottksmith95/repos. If you are wondering where the path /users/scottksmith95/repos came from, it came from the GitHub API documentation for Repos found here. Here is a trimmed down version of what this call returns:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
In the case of GitHub, the JSON returned is formatted very nicely. In many cases JSON will be returned without indentation or line breaks. If you run into this, there are many options available for formatting the JSON into a readable form. One such way is using JSON Formatter and Validator. This tool will not only pretty up the JSON, it will also validate it. A great tool to have in your toolbox.
It is all well and good to pull down JSON from an API using a web browser, but we are here to consume the data programmatically.
First we will create a class that will contain a static method for retrieving the JSON from the API as a string.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Now that we have the ability to make requests for JSON from web APIs, we need to do something useful with it.
The .NET framework has the
System.Web.Script.Serialization namespace. This namespace contains the
System.Web.Extensions. Here it is in action in the updated Program class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
If you were to step through the execution of this code with a debugger, you would notice that
jsonObject is an object array containing arrays of key value pairs that correspond to the JSON. This is definitely better than handling the JSON as a string, but we can do much better.
First off, we are going to switch to a different deserializer. The
With the Json.Net package installed, we will alter our existing Program class to use it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
So the code is now using Json.Net but it isn’t too different than before. We still have an object that has been created by deserializing the JSON. What we really need is a strongly typed object to store the data. For this we will create classes that will be used to store the JSON data. We could take the time to look at the JSON and manually create the classes. Instead, we are going to use a tool on the web that will do it for us. The tool is called json2csharp. We simply paste in the JSON we want classes for and it will generate them for us. Here are the classes it creates for us.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
If you examine the generated classes you may notice that the
mirror_url member is not strongly typed. It is of type
object because the JSON we submitted to the class generator contained null for the data. Because of this, the generated class used object instead of string (which is the actual type). When you run into cases like this, you will want to make sure and change them to the appropriate type. For our example it is not an issue so we will leave it alone.
The second item of note is the name of the root class. The tool named it RootObject because it is the root level object. We know what this is so we will rename it to
Finally, now that we have classes to represent the JSON data, we will update the Program class to deserialize the JSON into objects of these types.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
Now we are getting somewhere. We now have a
GitHubRepo objects that we can use programmatically. There is still one things bothering me. The member names of the JSON objects are not the greatest and don’t conform to most naming guidelines. What I want is to have properly named members yet still have the deserializer code able to deserialize each member. Json.Net has many different attributes that can be applied, but the one we will use is
JsonProperty. This property allows us to specify the name of the field to deserialize and to change the member name to anything we want. Here is an example.
That about wraps up this walk through on how to consume a JSON web API programmatically.
The final source code can be found here on GitHub.