TMDb, give me my json
In last post I presented TMDb that provides free movie data API. Let's see what has to be done to grab a json from API and digest it in UWP
How to get data from TMDb Api?
To perform any request on production API you have to pass unique api_key in parameter. How to obtain such key? First you have to create your account on themoviedb.org. If everything went well you can log in and navigate to your profile and then to API section (left side bar). Before you start generate of unique key you have to remember that you can do it only once per account. Generation of api_key requires details about your application, way of API utilization and some personal contact data.
After successful configuration you should see your API Key and example API request like this below (yes it's my very personal key, be my guest)
https://api.themoviedb.org/3/movie/550?api_key=da63548086e399ffc910fbc08526df05 |
Besides that, TMDb offers also a simple tool to track statistics of API utilization for your key, cool!
How to handle web API with UWP?
In Universal apps we have two different HttpClients to handle http protocol. First, introduced with .net 4.5 version (port for 4.0 exists as well) in System.Net.Http namespace and second, new one, in namespace Windows.Web.Http. What's the difference? Well... maybe I will dedicate a separate post to describe it deeper. At this moment everything we should know is that MSDN suggest that Windows.Web.Http should be preferred due to fact that System.Net.Http may become obsolete and finally removed in further versions (that's why i use System.Net.Http in examples ;D)
http = new HttpClient();
http.BaseAddress = new Uri( "http://api.themoviedb.org/3/");
var response = await http.GetAsync("movie/550?api_key=da63548086e399ffc910fbc08526df05" );
var jsonData = await response.Content.ReadAsStringAsync(); |
Above request will populate jsonData variable with json presented below. Our next step should convert it into something more relevant.
{
"adult": false,
"backdrop_path": "/hNFMawyNDWZKKHU4GYCBz1krsRM.jpg",
"belongs_to_collection": null,
"budget": 63000000,
"genres": [
{
"id": 18,
"name": "Drama"
}
],
"homepage": "",
"id": 550,
"imdb_id": "tt0137523",
"original_language": "en",
"original_title": "Fight Club",
"overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground \"fight clubs\" forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion.",
"popularity": 2.50307202280779,
"poster_path": "/2lECpi35Hnbpa4y46JX0aY3AWTy.jpg",
"production_companies": [
{
"name": "20th Century Fox",
"id": 25
},
{
"name": "Fox 2000 Pictures",
"id": 711
},
{
"name": "Regency Enterprises",
"id": 508
}
],
"production_countries": [
{
"iso_3166_1": "DE",
"name": "Germany"
},
{
"iso_3166_1": "US",
"name": "United States of America"
}
],
"release_date": "1999-10-14",
"revenue": 100853753,
"runtime": 139,
"spoken_languages": [
{
"iso_639_1": "en",
"name": "English"
}
],
"status": "Released",
"tagline": "How much can you know about yourself if you've never been in a fight?",
"title": "Fight Club",
"video": false,
"vote_average": 7.7,
"vote_count": 3185
} |
How to deal with Json?
Hopefully good old Newtonsoft.Json is present on UWP platform, so we have just to type it in our nuget. Now we should define class that will represent our Json i C# world. Please, don't do it manually (especially if you are writing example for a blog post in the middle of the night) you can use http://json2csharp.com/ that generates for you entire class or hierarchy of classes if json is more complex. For our json it generates below RootObject class with underlying Genre, ProductionCompany, ProductionCountry, SpokenLanguage classes
public class RootObject
{
public bool adult { get; set; }
public string backdrop_path { get; set; }
public object belongs_to_collection { get; set; } public int budget { get; set; }
public List<Genre> genres { get; set; }
public string homepage { get; set; }
public int id { get; set; }
public string imdb_id { get; set; }
public string original_language { get; set; }
public string original_title { get; set; }
public string overview { get; set; }
public double popularity { get; set; } public string poster_path { get; set; }
public List<ProductionCompany> production_companies { get ; set ; }
public List<ProductionCountry> production_countries { get ; set ; }
public string release_date { get; set; }
public int revenue { get; set; } public int runtime { get; set; }
public List<SpokenLanguage> spoken_languages { get ; set ; }
public string status { get; set; }
public string tagline { get; set; }
public string title { get; set; }
public bool video { get; set; }
public double vote_average { get; set; }
public int vote_count { get; set; }
} |
Now we can simply convert our jsonData string into relevant RootObject instance using Newtonsoft.Json in single line (doh! I love one-liners)
var result = JsonConvert.DeserializeObject<RootObject>(jsonData); |
As you probably see our RootObject properties look quite nasty compared to standard C# convention, you probably would like to see property names defined in PascalCase without underscores. With Resharper, fixing this issue is single Alt+Enter, unfortunately conversion between PascalCase and snake_case is not supported by JsonConverter by default - that means that in place of not matching property names we get null instead of expected values. In next post I'm going to show how to deal with this issue, how to handle not matching property types (let say that we want have List<>string> instead of List<>ProductionCompany>) or modify assigned values on the fly.
Cheers!