Software Design and Development :: CS 246

03 Prove

JSON APIs

Objectives

APIs

Companies with data-driven websites will often create APIs (Application Programming Interfaces), to allow people to programmatically pull data from their site.

Facebook, Twitter, Google Translate, and Ebay, are just a few examples of sites that provide public APIs.

Developers use APIs for a variety of reasons. Often, they want to pull specific types of data for data-mining. Other times, they might want to create their own applications that use the services of those companies, such as an iOS app that allows you to sell things on Ebay.

While every API is different, the general sequence of steps is usually the same:

  1. Sign up for a developer account (sometimes called an API Key) with the organization whose API you want to access and obtain authentication credentials.

  2. Send an HTTP request to authenticate with the API using the authentication credentials you were given and receive an authentication token.

  3. Use that authentication token to make API requests via HTTP to specific URLs (called "end points") which allow you to retrieve the data that you're interested in.

  4. The data is returned in a structured format. The most common data format for APIs is JSON.

Instructor Note:

For the API we will use for this assignment, rather than receiving a token, you simply pass the apikey to every endpoint request.

Assignment

You will write a program that uses the Open Weather Map API to retrieve weather information and forecasts.

Warning

This assignment is more difficult than any of your past assignments. I have purposefully left out many of the implementation details, which will force you to do quite a bit of research on your own.

Make sure you exercise diligence prior to asking for help.

Part I: Obtain an Open Weather Map API Account

As is the case for most popular APIs, Open Weather Map requires developers to first sign up for a developer account and acquire a set of API credentials before using their API.

  1. Go to https://openweathermap.org/ and sign up for a free account.

  2. After signing up, you will receive your API Key in an email (and it can also be seen on the web site). It looks something like: APPID=b98ff7327823823c8879261aabc9 .

    This APPID is your "username" and "password" to programmatically make requests from the API. You should treat it like you would any other password, and not share it with others or post it to GitHub, etc.

  3. Test your application token and the API by putting the following URL in the browser: https://api.openweathermap.org/data/2.5/weather?q=Rexburg&apiKey=b98ff7327823823c8879261aabc9 (of course, you'll first need to replace the API key in this URL with your own.) This should bring back JSON data corresponding to the current weather in Rexburg.

Security Warning

Note that some of these items are labeled Secret for a reason. You should not share these values with anyone. You should remove them from your code before submitting it.

With these token values, anyone can access this API as if they were you.

This same caution is generally true for all APIs that use authentication tokens.

Part II: Connect to the API with Java

We'll be using the GSON library to help us interpret the data, just like we did in the team activity. (Please refer to the team activity for more information about using GSON.)

In addition to the GSON library, we will make use of the built-in URLConnection class in Java to help make our web requests.

Please read over at least the first part of StackOverflow: How to use java.net.URLConnection to fire and handle HTTP requests. Please note that we will be using HTTP Get requests with query parameters.

Following the example on the above StackOverflow article (and potentially other Web references), complete the following:

  1. Create a new IntelliJ project.

  2. Add a reference to the GSON library as you did for the team activity assignment.

  3. Follow the example above of HTTP Get requests to make a request to the same endpoint you did earlier in the browser, and verify that you can get the JSON response back and display it to the screen using Java.

Part III: Create a Class to Store the Data

There is a lot of information in the responses we will get back, but for this assignment we only care about some of it.

As we did in the teach assignment, we'll be creating a class to hold just the data we're interested in.

  1. First, create a WeatherConditions class that can hold some of the information you are retrieving back. To start with, it should contain:

    • id

    • name

    • main

    Notice that id is an integer, name is a String. On the other hand, main might look something like this:

    
    "main": {
        "temp": 286.99,
        "pressure": 1013,
        "humidity": 53,
        "temp_min": 286.45,
        "temp_max": 287.55
    }                    
    

    Where it maps a key of type String to a value of type float (e.g., "temp" is a key that maps to a value of 286.99). Thus, you might choose a data structure, like Map which has generic types, String for the key and Float for the value, such as Map<String, Float>.

  2. Verify that you can load the current conditions and use GSON to deserialize them into a WeatherConditions object.

  3. Now, when the GSON library deserializes a JSON String into a class instance, it expects the key names in the JSON to exactly match the variable names of the class.

    Sometimes this isn't ideal, such as a name like "main", so it provides a way for you to specify which JSON key should connect to a given variable in a class.

    In our case, let's change the name of our main member variable to measurements and then tell GSON, to match the two up. To do so, we need to add an "annotation" to our variable to tell GSON that "main" should go with measurements.

    Modify the declaration of measurements in your class so it contains the following line, right before the member variable is declared:

    @SerializedName("main")
    
  4. Add to your program the ability to prompt the user for a city name and use it, rather than always using "Rexburg" in your API calls.

  5. Verify that you can use your code to request data for different cities, and that you can use your measurements map to display the current temperature for each one.

    As you do so, you'll likely notice that by default, it displays temperature in Kelvins, which is likely not your preferred unit of measurement.

    Look into the API information on their website and figure out how to change your call so that you can have them send you the temperature in your preferred units.

Part IV: Working with Forecasts

In the previous part, we obtained current conditions for a given city. In this part, we will request forecasts for a city rather than simply its current conditions.

The forecast API for 5 day weather forecasts (getting forecasts for 3 hour increments during these 5 days) is outlined here: https://openweathermap.org/forecast5 .

Using this API endpoint, follow these steps to add additional functionality to your program:

  1. Create a WeatherForecast class that matches up with the results of this endpoint. Notice that this contains a list of individual forecast items or events for every 3 hour period.

  2. Create a WeatherForecastItem class that contains the information of the 3 hour period.

    Make sure that when you deserialize your JSON, it creates a WeatherForecast object that contains a list of WeatherForecastItems.

  3. Each WeatherForecastItem should contain "main" measurements information, "weather" a list of possible weather conditions, wind, and the time (dt or dt_txt) for the forecast.

    Choose appropriate data types to deserialize each of these items to. Some of these could be new classes that you create, others could make use of collections (e.g., Maps, Lists, etc.).

  4. Have the program give the user a forecast for their specified city. It should display a list of the following for each 3 hour period:

    • Time

    • Temperature

    • A description of the weather conditions (e.g., "clear sky")

    • Wind speed

Once you've made it this far, move on the stretch challenge.

🌟Stretch Challenge🌟

  1. Rather than work with a single city, use a list of at least 5. (You can either allow the user to type them in, or you can have them hard-coded into your Java code.)

  2. For each city in the set, obtain the weather forecast.

  3. Prepare a data structure that contains the city as well as the maximum temperature and the maximum wind speed expected at any point in its upcoming 5-day forecast.

  4. Sort the cities by maximum temperature and display the results. Then, perform a separate sort, this time by maximum wind, speed and display the results.

There are several ways to accomplish this. The most elegant methods make use of Collections.sort() and either a custom Comparator class, or a lambda function.