Marc Hauschildt
Web Technologies and Computer Software Development Instructor at Kirkwood Community College in Cedar Rapids, IA.
Week 8
Students will demonstrate an understanding multitier software design
Students will understand the use of standard collections and generics in the Java programming language
Students will understand elementary Thread programming in Java
Students will create software that performs standard data operations with Java and a relational database
Students will use streams to communicate with sockets and files
Students will apply elementary XML functionality in Java
Students will understand the importance of using standard Object Oriented Programming (OOP) design tools such as the Unified Modeling Language (UML)
Students will demonstrate a preference for messages and Exceptions for communicating between components
Students will systematize Test Driven Development
{ and ends with } {role: "test", content: "example"}Sign up for a free TMDB account.
https://www.themoviedb.org/signup
After logging in, going to your profile page.
https://www.themoviedb.org/settings/profile
Click API to generate an API Read Access Token and API Key.
Add new properties for your API token and URL.
You will need the read access token, not the api key
datasource.type=json
json.apiReadAccessToken=<your-token>
json.apiURL=https://api.themoviedb.org/3/search/movie?
In the doa.impl package, create a new class called "JsonMovieDAO". Have this class implement the MovieDAO interface and the search method.
Set this class up similar to the XMLMovieDAO, but with two attributes, one for the URL and one for the key.
package edu.kirkwood.dao.impl;
import edu.kirkwood.dao.MovieDAO;
import edu.kirkwood.model.Movie;
import java.util.List;
public class JsonMovieDAO implements MovieDAO {
private String apiURL;
private String apiToken;
public JsonMovieDAO(String apiURL, String apiToken) {
this.apiURL = apiURL;
this.apiToken = apiToken;
}
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A List<Movie> movies that matches the search title
*/
@Override
public List<Movie> search(String title) {
return List.of();
}
}
Create a getResponseBody method that takes in the title search String and returns a String output.
Use an OkHttpClient object to make the GET request to the API.
The Request object must follow the API's documentation.
package edu.kirkwood.dao.impl;
import edu.kirkwood.dao.MovieDAO;
import edu.kirkwood.model.Movie;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.List;
public class JsonMovieDAO implements MovieDAO {
private String apiURL;
private String apiToken;
public JsonMovieDAO(String apiURL, String apiToken) {
this.apiURL = apiURL;
this.apiToken = apiToken;
}
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A List<Movie> movies that matches the search title
*/
@Override
public List<Movie> search(String title) {
String responseBody = fetchRawData(title);
System.out.println("Response Body: " + responseBody);
return List.of();
}
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A Json String of movies that matches the search title
*/
public String fetchRawData(String title) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(apiURL + "&query=" + title)
.get()
.addHeader("accept", "application/json")
.addHeader("Authorization", "Bearer " + apiToken)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
throw new RuntimeException(e);
}
String responseBody = "";
try {
responseBody = response.body().string();
} catch (IOException e) {
throw new RuntimeException(e);
}
return responseBody;
}
}
Update the getDAO() method to handle JSON.
Get the two json application properties.
Pass those values to the JsonMovieDAO constructor.
package edu.kirkwood.dao;
import edu.kirkwood.dao.impl.JsonMovieDAO;
import edu.kirkwood.dao.impl.MySQLMovieDAO;
import edu.kirkwood.dao.impl.XmlMovieDAO;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class MovieDAOFactory {
private static Properties properties = new Properties();
static {
try(InputStream is = MovieDAOFactory.class.getClassLoader()
.getResourceAsStream("application.properties")) {
if(is == null) {
throw new FileNotFoundException("application.properties file not found");
}
properties.load(is);
} catch(IOException e) {
e.printStackTrace();
}
}
/**
* To retrieve a MovieDAO based on application.properties settings
* @return A MovieDAO (XMLMovieDAO, MySQLMovieDAO, JSONMovieDAO, etc.)
*/
public static MovieDAO getMovieDAO() {
String dataSourceType = properties.getProperty("datasource.type");
if(dataSourceType == null || dataSourceType.isEmpty()) {
throw new IllegalArgumentException("datasource.type is required");
}
switch (dataSourceType.toUpperCase()) {
case "XML":
String apiURL = properties.getProperty("xml.apiURL");
if(apiURL == null || apiURL.isEmpty()) {
throw new IllegalArgumentException("xml.apiURL is required");
}
return new XmlMovieDAO(apiURL);
case "JSON":
String jsonApiURL = properties.getProperty("json.apiURL");
if(jsonApiURL == null || jsonApiURL.isEmpty()) {
throw new IllegalArgumentException("json.apiURL is required");
}
String jsonReadAccessToken = properties.getProperty("json.apiReadAccessToken");
if(jsonReadAccessToken == null || jsonReadAccessToken.isEmpty()) {
throw new IllegalArgumentException("json.apiReadAccessToken");
}
return new JsonMovieDAO(jsonApiURL, jsonReadAccessToken);
case "MYSQL":
return new MySQLMovieDAO();
// case "MONGODB":
// break;
default:
throw new RuntimeException("Unsupported data source type: " + dataSourceType);
}
}
}
Update the main method to call the JsonMovieDAO's search method.
Run the program. Raw movie data will display.
package edu.kirkwood;
import edu.kirkwood.dao.MovieDAO;
import edu.kirkwood.dao.MovieDAOFactory;
import edu.kirkwood.dao.impl.JsonMovieDAO;
import edu.kirkwood.dao.impl.MySQLMovieDAO;
import edu.kirkwood.dao.impl.XmlMovieDAO;
import edu.kirkwood.model.Movie;
import edu.kirkwood.model.xml.MovieSearchResult;
import java.util.ArrayList;
import java.util.List;
public class MyDataApp {
public static void main(String[] args) {
MovieDAO movieDAO = MovieDAOFactory.getMovieDAO();
// Prompt the user for a movie title
String title = "Short Circuit";
List<Movie> results = new ArrayList<>();
if(movieDAO instanceof XmlMovieDAO) {
XmlMovieDAO xmlMovieDAO = (XmlMovieDAO) movieDAO;
results = xmlMovieDAO.search(title);
} else if(movieDAO instanceof MySQLMovieDAO) {
MySQLMovieDAO mySQLMovieDAO = (MySQLMovieDAO) movieDAO;
results = mySQLMovieDAO.search(title);
} else if(movieDAO instanceof JsonMovieDAO) {
JsonMovieDAO mySQLMovieDAO = (JsonMovieDAO) movieDAO;
results = mySQLMovieDAO.search(title);
}
results.forEach(System.out::println);
}
}
Raw JSON data is very hard to read.
In the JsonMovieDAO class, create a method called prettyPrintResponse().
Gson is used to read and format JSON.
package edu.kirkwood.dao.impl;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import edu.kirkwood.dao.MovieDAO;
import edu.kirkwood.model.Movie;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
public class JsonMovieDAO implements MovieDAO {
private String apiURL;
private String apiToken;
public JsonMovieDAO(String apiURL, String apiToken) {
this.apiURL = apiURL;
this.apiToken = apiToken;
}
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A List<Movie> movies that matches the search title
*/
@Override
public List<Movie> search(String title) {
String responseBody = getResponseBody(title);
prettyPrintResponse(responseBody);
return List.of();
}
public void prettyPrintResponse(String responseBody) {
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
JsonElement jsonElement = new JsonParser().parse(responseBody);
String json = gson.toJson(jsonElement);
System.out.print(json);
}
public String getResponseBody(String title) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(apiURL + "&query=" + title)
.get()
.addHeader("accept", "application/json")
.addHeader("Authorization", "Bearer " + apiToken)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
throw new RuntimeException(e);
}
String responseBody = "";
try {
responseBody = response.body().string();
} catch (IOException e) {
throw new RuntimeException(e);
}
return responseBody;
}
}
Create a new models package called "json".
Create a new class called MovieSearchResult.
Add attributes representing a single Movie Json result.
Note that this API uses "overview" instead of "plot".
The LocalDate release_date is currently commented out. We'll handle that data type later.
package edu.kirkwood.model.json;
import java.time.LocalDate;
public class MovieSearchResult {
private String id;
private String title;
private String overview;
// private LocalDate release_date;
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public String getOverview() {
return overview;
}
// public LocalDate getRelease_date() {
// return release_date;
// }
@Override
public String toString() {
return "MovieSearchResult{" +
"id=" + id +
", title='" + title + '\'' +
", overview='" + overview + '\'' +
// ", release_date=" + release_date +
'}';
}
}Inside the "models.json" package, create a new class called TmdbMovieResponse.
Add an attribute representing a List of MovieSearchResult objects.
The word "results" is the name of the array returned from the API.
package edu.kirkwood.model.json;
import java.util.List;
public class TmdbMovieResponse {
private List<MovieSearchResult> results;
public List<MovieSearchResult> getResults() {
return results;
}
}
Update the search method to convert the raw data into a TmdbMovieResponse object.
Gson will take the value of the JSON's "results" array and set it to the TmdbMovieResponse's "results" List.
Gson will take the values of each movie id, title, and overview to MovieSearchResult object and automatically add it to the list.
We can loop through the List returned from getResults().
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A List<Movie> movies that matches the search title
*/
@Override
public List<Movie> search(String title) {
String rawData = getRawData(title);
// System.out.println(prettyFormatter(rawData));
Gson gson = new GsonBuilder().create();
TmdbMovieResponse movieResponse = null;
try {
movieResponse = gson.fromJson(rawData, TmdbMovieResponse.class);
} catch (JsonSyntaxException | JsonIOException e) {
// Will display an error if the json is not a valid
// representation for a TmdbMovieResponse object
throw new RuntimeException(e);
}
movieResponse.getResults().forEach(result -> {
System.out.println(result);
});
return List.of();
}In the json.MovieSearchResult class, uncomment the LocalDate release_date code.
If you run the program, you will get an error saying "com.google.gson.JsonIOException: Failed making field 'java.time.LocalDate#year' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type."
package edu.kirkwood.model.json;
import java.time.LocalDate;
public class MovieSearchResult {
private String id;
private String title;
private String overview;
private LocalDate release_date;
public String getId() {
return id;
}
public String getTitle() {
return title;
}
public String getOverview() {
return overview;
}
public LocalDate getRelease_date() {
return release_date;
}
@Override
public String toString() {
return "MovieSearchResult{" +
"id=" + id +
", title='" + title + '\'' +
", overview='" + overview + '\'' +
", release_date=" + release_date +
'}';
}
}In the DAO package, create a new class called JsonTypeAdapter.
Add a custom TypeAdapter class for any class in the java.time package, like LocalDate, LocalDateTime, Instant.
To put a class inside a class, we need to make them static.
The try-catch statements are needed in case a JSON object doesn't have a valid date, such as an empty string.
package edu.kirkwood.dao;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.*;
import java.time.format.DateTimeParseException;
public class JsonTypeAdapter {
/**
* Used by Gson when date is formatted like "1967-07-23"
*/
public static class LocalDateDeserializer implements JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
try {
return LocalDate.parse(json.getAsString());
} catch (DateTimeParseException e) {
return null;
}
}
}
/**
* Used by Gson when date is formatted like "1967-07-23T09:18:33"
*/
public static class LocalDateTimeDeserializer implements JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
try {
return LocalDateTime.parse(json.getAsString());
} catch (DateTimeParseException e) {
return null;
}
}
}
/**
* Used by Gson when date is formatted like "1967-07-23T09:18:33.666Z"
*/
public static class InstantDeserializer implements JsonDeserializer<Instant> {
@Override
public Instant deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
try {
return Instant.parse(json.getAsString());
} catch (DateTimeParseException e) {
return null;
}
}
}
}
In the JsonMovieDAO class's search method, edit the Gson object by chaining the .registerTypeAdapter() method.
Because the JSON release_date is something like "1967-07-23", we will pass LocalDate.class as the first argument and a type Adapter class as the second argument.
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A List<Movie> movies that matches the search title
*/
@Override
public List<Movie> search(String title) {
String rawData = getRawData(title);
// System.out.println(prettyFormatter(rawData));
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new JsonTypeAdapter.LocalDateDeserializer())
.create();
TmdbMovieResponse movieResponse = null;
try {
movieResponse = gson.fromJson(rawData, TmdbMovieResponse.class);
} catch (JsonSyntaxException | JsonIOException e) {
// Will display an error if the json is not a valid
// representation for a TmdbMovieResponse object
throw new RuntimeException(e);
}
movieResponse.getResults().forEach(result -> {
System.out.println(result);
});
return List.of();
}In the search method, instantiate a List<Movie> object.
Inside the forEach loop, instantiate Movie objects and add them to the list.
Since the MovieSearchResult's release_date might be null, we have to write an if statement so the getYear() method is only called when the LocalDate object exists.
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A List<Movie> movies that matches the search title
*/
@Override
public List<Movie> search(String title) {
List<Movie> movies = new ArrayList<>();
String rawData = getRawData(title);
// System.out.println(prettyFormatter(rawData));
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new JsonTypeAdapter.LocalDateDeserializer())
.create();
TmdbMovieResponse movieResponse = null;
try {
movieResponse = gson.fromJson(rawData, TmdbMovieResponse.class);
} catch (JsonSyntaxException | JsonIOException e) {
// Will display an error if the json is not a valid
// representation for a TmdbMovieResponse object
throw new RuntimeException(e);
}
movieResponse.getResults().forEach(result -> {
Movie movie = new Movie();
movie.setId(result.getId());
movie.setTitle(result.getTitle());
if(result.getRelease_date() != null) {
movie.setYear(result.getRelease_date().getYear());
}
movie.setPlot(result.getOverview());
movies.add(movie);
});
return movies;
}The Movie DB API return's a "total_pages" and "total_results" properties as part of the response.
Add total_pages as an attribute to the TmdbMovieResponse class
Add a getter method.
package edu.kirkwood.model.json;
import java.util.List;
public class TmdbMovieResponse {
private List<MovieSearchResult> results;
private int total_pages;
public List<MovieSearchResult> getResults() {
return results;
}
public int getTotal_pages() {
return total_pages;
}
}
Update the JsonMovieDAO's getRawData method to accept a page number as input.
Concatenate that value to the apiURL.
/**
* Get raw data from themoviedb.org search API
* @param title The movie title a user is searching for
* @param page The page number to retrieve
* @return A JSON string returned from the API
*/
public String getRawData(String title, int page) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(apiURL + "query=" + title + "&page=" + page)
.get()
.addHeader("accept", "application/json")
.addHeader("Authorization", "Bearer " + apiToken)
.build();
Response response = null;
String responseBody = "";
try {
response = client.newCall(request).execute();
responseBody = response.body().string();
} catch(IOException e) {
throw new RuntimeException(e);
}
return responseBody;
}Update the JsonMovieDAO's search method to run a while loop, passing the current page number to the getRawData method.
Run the loop continually until all pages have been retrieved.
/**
* Retrieves all movies from the data source that matches the title
* @param title The movie title a user is searching for
* @return A List<Movie> movies that matches the search title
*/
@Override
public List<Movie> search(String title) {
List<Movie> movies = new ArrayList<>();
int currentPage = 1;
while(true) {
String rawData = getRawData(title, currentPage);
// System.out.println(prettyFormatter(rawData));
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new JsonTypeAdapter.LocalDateDeserializer())
.create();
TmdbMovieResponse movieResponse = null;
try {
movieResponse = gson.fromJson(rawData, TmdbMovieResponse.class);
} catch (JsonSyntaxException | JsonIOException e) {
// Will display an error if the json is not a valid
// representation for a TmdbMovieResponse object
throw new RuntimeException(e);
}
movieResponse.getResults().forEach(result -> {
Movie movie = new Movie();
movie.setId(result.getId());
movie.setTitle(result.getTitle());
if (result.getRelease_date() != null) {
movie.setYear(result.getRelease_date().getYear());
}
movie.setPlot(result.getOverview());
movies.add(movie);
});
if(movieResponse.getTotal_pages() > currentPage) {
currentPage++;
} else {
break;
}
}
return movies;
}import com.google.gson.*;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.lang.reflect.Type;
import java.time.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer())
.create();
// JsonElement jsonElement = new JsonParser().parse(responseBody);
// String json = gson.toJson(jsonElement);
// System.out.print(json);
MovieDBAPI movieDBAPI = null;
try {
movieDBAPI = gson.fromJson(responseBody, MovieDBAPI.class);
} catch (JsonSyntaxException | JsonIOException e) {
System.out.println(e.getMessage());
System.exit(0);
}
for(Movie movie : movieDBAPI.results) {
System.out.println("ID: " + movie.id);
System.out.println("Title: " + movie.title);
System.out.println("Overview: " + movie.overview);
System.out.println("Genres: " + Arrays.toString(movie.genre_ids));
System.out.println("Vote Average: " + movie.vote_average);
System.out.println("Video: " + (movie.video ? "Yes" : "No"));
System.out.println("Release Date: " + movie.release_date);
System.out.println();
}
}
private static class MovieDBGenre {
public Genre[] genres;
}
private static class Genre {
public int id;
public String name;
}
private static class MovieDBAPI {
public Movie[] results;
}
private static class Movie {
public int id;
public String title;
public String overview;
public int[] genre_ids;
public double vote_average;
public boolean video;
public LocalDate release_date;
}
}-> indicates a lamba expression-> must be a boolean expression.import com.google.gson.*;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.lang.reflect.Type;
import java.time.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class JsonDemo3 {
public static void main(String[] args) throws IOException {
// Remove before pushing to GitHub
String apiKey = "";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.themoviedb.org/3/trending/movie/day?language=en-US")
.get()
.addHeader("accept", "application/json")
.addHeader("Authorization", "Bearer " + apiKey)
.build();
Request request2 = new Request.Builder()
.url("https://api.themoviedb.org/3/genre/movie/list?language=en")
.get()
.addHeader("accept", "application/json")
.addHeader("Authorization", "Bearer " + apiKey)
.build();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
// System.out.println(responseBody);
Response response2 = client.newCall(request2).execute();
String responseBody2 = response2.body().string();
// System.out.println(responseBody2);
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapter(LocalDate.class, new LocalDateDeserializer())
.create();
// JsonElement jsonElement = new JsonParser().parse(responseBody);
// String json = gson.toJson(jsonElement);
// System.out.print(json);
MovieDBAPI movieDBAPI = null;
try {
movieDBAPI = gson.fromJson(responseBody, MovieDBAPI.class);
} catch (JsonSyntaxException | JsonIOException e) {
System.out.println(e.getMessage());
System.exit(0);
}
MovieDBGenre movieDBGenre = null;
try {
movieDBGenre = gson.fromJson(responseBody2, MovieDBGenre.class);
} catch (JsonSyntaxException | JsonIOException e) {
System.out.println(e.getMessage());
System.exit(0);
}
Genre[] genres = movieDBGenre.genres;
List<Genre> genresList = Arrays.asList(genres);
for(Movie movie : movieDBAPI.results) {
System.out.println("ID: " + movie.id);
System.out.println("Title: " + movie.title);
System.out.println("Overview: " + movie.overview);
// System.out.println("Genres: " + Arrays.toString(movie.genre_ids));
System.out.print("Genres: ");
for(int id: movie.genre_ids){
Genre genre = genresList.stream().filter(a -> a.id == id).collect(Collectors.toList()).get(0);
System.out.print(genre.name + ", ");
}
System.out.println();
System.out.println("Vote Average: " + movie.vote_average);
System.out.println("Video: " + (movie.video ? "Yes" : "No"));
System.out.println("Release Date: " + movie.release_date);
System.out.println();
}
}
private static class LocalDateDeserializer implements JsonDeserializer<LocalDate> {
@Override
public LocalDate deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
return LocalDate.parse(json.getAsString());
}
}
private static class MovieDBGenre {
public Genre[] genres;
}
private static class Genre {
public int id;
public String name;
}
private static class MovieDBAPI {
public Movie[] results;
}
private static class Movie {
public int id;
public String title;
public String overview;
public int[] genre_ids;
public double vote_average;
public boolean video;
public LocalDate release_date;
}
}import com.google.gson.Gson;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class JsonDemo2 {
private static final String API_URL = "https://randomuser.me/api/?format=json&seed=abc&results=1&nat=us";
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(API_URL)
.build();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
// System.out.println(responseBody);
Gson gson = new Gson();
APIResponse apiResponse = gson.fromJson(responseBody, APIResponse.class);
for (Person person : apiResponse.results) {
System.out.println(person.name.first + " " + person.name.last);
System.out.printf("%d %s\n", person.location.street.number, person.location.street.name);
System.out.printf("%s, %s %s\n", person.location.city, person.location.state, person.location.postcode);
System.out.printf("Latitude: %.4f, Longitude: %.4f\n", person.location.coordinates.latitude, person.location.coordinates.longitude);
System.out.println(person.email);
}
}
private static class APIResponse {
private Person[] results;
}
private static class Person {
private Name name;
private Location location;
private String email;
}
private static class Name {
private String first;
private String last;
}
private static class Location {
private Street street;
private String city;
private String state;
private int postcode;
private Coordinates coordinates;
}
private static class Street {
private int number;
private String name;
}
private static class Coordinates {
private double latitude;
private double longitude;
}
}package edu.kirkwood;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class JsonDemo2 {
private static final String API_URL = "https://randomuser.me/api/?format=json&seed=abc&results=1&nat=us";
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(API_URL)
.build();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
// System.out.println(responseBody);
Gson gson = new Gson();
APIResponse apiResponse = null;
try {
apiResponse = gson.fromJson(responseBody, APIResponse.class);
} catch(JsonSyntaxException e) {
System.out.println("ERROR: " + e.getMessage());
System.exit(0);
}
for (Person person : apiResponse.results) {
System.out.println(person.name.first + " " + person.name.last);
System.out.printf("%d %s\n", person.location.street.number, person.location.street.name);
System.out.printf("%s, %s %s\n", person.location.city, person.location.state, person.location.postcode);
System.out.printf("Latitude: %.4f, Longitude: %.4f\n", person.location.coordinates.latitude, person.location.coordinates.longitude);
System.out.println(person.email);
}
}
private static class APIResponse {
private Person[] results;
}
private static class Person {
private Name name;
private Location location;
private String email;
}
private static class Name {
private String first;
private String last;
}
private static class Location {
private Street street;
private String city;
private String state;
private int postcode;
private Coordinates coordinates;
}
private static class Street {
private int number;
private int name;
}
private static class Coordinates {
private double latitude;
private double longitude;
}
}
import com.google.gson.*;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.lang.reflect.Type;
import java.time.Instant;
public class JsonDemo2 {
private static final String API_URL = "https://randomuser.me/api/?format=json&seed=abc&results=1&nat=us";
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(API_URL)
.build();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
// System.out.println(responseBody);
Gson gson = new GsonBuilder()
.registerTypeAdapter(Instant.class, new InstantDeserializer())
.create();
APIResponse apiResponse = null;
try {
apiResponse = gson.fromJson(responseBody, APIResponse.class);
} catch(JsonSyntaxException e) {
System.out.println("ERROR: " + e.getMessage());
System.exit(0);
}
for (Person person : apiResponse.results) {
System.out.println(person.name.first + " " + person.name.last);
System.out.printf("%d %s\n", person.location.street.number, person.location.street.name);
System.out.printf("%s, %s %s\n", person.location.city, person.location.state, person.location.postcode);
System.out.printf("Latitude: %.4f, Longitude: %.4f\n", person.location.coordinates.latitude, person.location.coordinates.longitude);
System.out.println(person.email);
System.out.printf("Born %s\n", person.dob.date);
}
}
private static class InstantDeserializer implements JsonDeserializer<Instant> {
@Override
public Instant deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
return Instant.parse(json.getAsString());
}
}
private static class APIResponse {
private Person[] results;
}
private static class Person {
private Name name;
private Location location;
private String email;
private DateOfBirth dob;
}
private static class Name {
private String first;
private String last;
}
private static class Location {
private Street street;
private String city;
private String state;
private int postcode;
private Coordinates coordinates;
}
private static class Street {
private int number;
private String name;
}
private static class Coordinates {
private double latitude;
private double longitude;
}
private static class DateOfBirth {
private Instant date;
}
}import com.google.gson.*;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.lang.reflect.Type;
import java.time.Instant;
import java.util.Arrays;
public class JsonDemo2 {
private static final String API_URL = "https://randomuser.me/api/?format=json&seed=abc&results=5&nat=us";
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(API_URL)
.build();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
// System.out.println(responseBody);
Gson gson = new GsonBuilder()
.registerTypeAdapter(Instant.class, new InstantDeserializer())
.create();
APIResponse apiResponse = null;
try {
apiResponse = gson.fromJson(responseBody, APIResponse.class);
} catch(JsonSyntaxException e) {
System.out.println("ERROR: " + e.getMessage());
System.exit(0);
}
Person[] people = apiResponse.results;
Arrays.sort(people);
for(Person person: people) {
System.out.println(person.name.first + " " + person.name.last);
System.out.printf("%d %s\n", person.location.street.number, person.location.street.name);
System.out.printf("%s, %s %s\n", person.location.city, person.location.state, person.location.postcode);
System.out.printf("Latitude: %.4f, Longitude: %.4f\n", person.location.coordinates.latitude, person.location.coordinates.longitude);
System.out.println(person.email);
System.out.printf("Born %s\n", person.dob.date);
System.out.println();
}
}
private static class InstantDeserializer implements JsonDeserializer<Instant> {
@Override
public Instant deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
return Instant.parse(json.getAsString());
}
}
private static class APIResponse {
private Person[] results;
}
private static class Person implements Comparable<Person> {
private Name name;
private Location location;
private String email;
private DateOfBirth dob;
@Override
public int compareTo(Person o) {
int result = this.name.last.compareTo(o.name.last);
if (result == 0) {
result = this.name.first.compareTo(o.name.first);
}
return result;
}
}
private static class Name {
private String first;
private String last;
}
private static class Location {
private Street street;
private String city;
private String state;
private int postcode;
private Coordinates coordinates;
}
private static class Street {
private int number;
private String name;
}
private static class Coordinates {
private double latitude;
private double longitude;
}
private static class DateOfBirth {
private Instant date;
}
}By Marc Hauschildt
Web Technologies and Computer Software Development Instructor at Kirkwood Community College in Cedar Rapids, IA.