Parsing multiple JSON objects that exist in one line in Java - java

I'm currently using the OMDB API, which can either return get-queries as JSON objects or XML. Working with JSON is something I'd like to learn, and it generally seems like best solution for what I'm trying to do. The implementation I'm hoping for, is to allow the user to search for a movie, and select the correct one from a list. I'm currently using the google.gson library.
The problem I've run in to, is that the searching for movies by a title with OMDB, this example being "batman", returns the following String:
{"Search":[{"Title":"Batman Begins","Year":"2005","imdbID":"tt0372784","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BOTY4YjI2N2MtYmFlMC00ZjcyLTg3YjEtMDQyM2ZjYzQ5YWFkXkEyXkFqcGdeQXVyMTQxNzMzNDI#._V1_SX300.jpg"},{"Title":"Batman v Superman: Dawn of Justice","Year":"2016","imdbID":"tt2975590","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BYThjYzcyYzItNTVjNy00NDk0LTgwMWQtYjMwNmNlNWJhMzMyXkEyXkFqcGdeQXVyMTQxNzMzNDI#._V1_SX300.jpg"},{"Title":"Batman","Year":"1989","imdbID":"tt0096895","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BMTYwNjAyODIyMF5BMl5BanBnXkFtZTYwNDMwMDk2._V1_SX300.jpg"},{"Title":"Batman Returns","Year":"1992","imdbID":"tt0103776","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BOGZmYzVkMmItM2NiOS00MDI3LWI4ZWQtMTg0YWZkODRkMmViXkEyXkFqcGdeQXVyODY0NzcxNw##._V1_SX300.jpg"},{"Title":"Batman Forever","Year":"1995","imdbID":"tt0112462","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BNDdjYmFiYWEtYzBhZS00YTZkLWFlODgtY2I5MDE0NzZmMDljXkEyXkFqcGdeQXVyMTMxODk2OTU#._V1_SX300.jpg"},{"Title":"Batman & Robin","Year":"1997","imdbID":"tt0118688","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BMGQ5YTM1NmMtYmIxYy00N2VmLWJhZTYtN2EwYTY3MWFhOTczXkEyXkFqcGdeQXVyNTA2NTI0MTY#._V1_SX300.jpg"},{"Title":"The Lego Batman Movie","Year":"2017","imdbID":"tt4116284","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BMTcyNTEyOTY0M15BMl5BanBnXkFtZTgwOTAyNzU3MDI#._V1_SX300.jpg"},{"Title":"Batman: The Animated Series","Year":"1992–1995","imdbID":"tt0103359","Type":"series","Poster":"https://m.media-amazon.com/images/M/MV5BOTM3MTRkZjQtYjBkMy00YWE1LTkxOTQtNDQyNGY0YjYzNzAzXkEyXkFqcGdeQXVyOTgwMzk1MTA#._V1_SX300.jpg"},{"Title":"Batman: Under the Red Hood","Year":"2010","imdbID":"tt1569923","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BNmY4ZDZjY2UtOWFiYy00MjhjLThmMjctOTQ2NjYxZGRjYmNlL2ltYWdlL2ltYWdlXkEyXkFqcGdeQXVyNTAyODkwOQ##._V1_SX300.jpg"},{"Title":"Batman: The Dark Knight Returns, Part 1","Year":"2012","imdbID":"tt2313197","Type":"movie","Poster":"https://m.media-amazon.com/images/M/MV5BMzIxMDkxNDM2M15BMl5BanBnXkFtZTcwMDA5ODY1OQ##._V1_SX300.jpg"}],"totalResults":"490","Response":"True"}
Thus far, I've managed to remove the {"Search":[ and ],"totalResults":"490","Response":"True"} part using sendGetRequest(requestURL).substring(11, sendGetRequest(requestURL).length()-41);, yet I still can't seem to parse the String as JSON. I've tried using String.split and Matcher/Pattern with various regexes, to separate the the JsonObjects. I've also tried a JSONArray, but to no avail.
I'm new to working with JSON, so it's not unlikely I'm missing something obvious or have completely misunderstood JSON in general.

First define a new custom class for your need:
import com.fasterxml.jackson.annotation.JsonProperty;
public class YourClass {
#JsonProperty("Title")
private String title;
#JsonProperty("Year")
private String year;
private String imdbID;
#JsonProperty("Type")
private String type;
#JsonProperty("Poster")
private String poster;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getImdbID() {
return imdbID;
}
public void setImdbID(String imdbID) {
this.imdbID = imdbID;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPoster() {
return poster;
}
public void setPoster(String poster) {
this.poster = poster;
}
#Override
public String toString() {
return "YourClass{" +
"title='" + title + '\'' +
", year='" + year + '\'' +
", imdbID='" + imdbID + '\'' +
", type='" + type + '\'' +
", poster='" + poster + '\'' +
'}';
}
}
Then simply you can parse your JSON, this is main method:
public static void main(String[] args) throws JsonProcessingException {
SpringApplication.run(Demo2Application.class, args);
ObjectMapper objectMapper = new ObjectMapper();
List<YourClass> yourClassList = objectMapper.readValue("[{\"Title\":\"Batman Begins\",\"Year\":\"2005\",\"imdbID\":\"tt0372784\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BOTY4YjI2N2MtYmFlMC00ZjcyLTg3YjEtMDQyM2ZjYzQ5YWFkXkEyXkFqcGdeQXVyMTQxNzMzNDI#._V1_SX300.jpg\"},{\"Title\":\"Batman v Superman: Dawn of Justice\",\"Year\":\"2016\",\"imdbID\":\"tt2975590\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BYThjYzcyYzItNTVjNy00NDk0LTgwMWQtYjMwNmNlNWJhMzMyXkEyXkFqcGdeQXVyMTQxNzMzNDI#._V1_SX300.jpg\"},{\"Title\":\"Batman\",\"Year\":\"1989\",\"imdbID\":\"tt0096895\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTYwNjAyODIyMF5BMl5BanBnXkFtZTYwNDMwMDk2._V1_SX300.jpg\"},{\"Title\":\"Batman Returns\",\"Year\":\"1992\",\"imdbID\":\"tt0103776\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BOGZmYzVkMmItM2NiOS00MDI3LWI4ZWQtMTg0YWZkODRkMmViXkEyXkFqcGdeQXVyODY0NzcxNw##._V1_SX300.jpg\"},{\"Title\":\"Batman Forever\",\"Year\":\"1995\",\"imdbID\":\"tt0112462\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BNDdjYmFiYWEtYzBhZS00YTZkLWFlODgtY2I5MDE0NzZmMDljXkEyXkFqcGdeQXVyMTMxODk2OTU#._V1_SX300.jpg\"},{\"Title\":\"Batman & Robin\",\"Year\":\"1997\",\"imdbID\":\"tt0118688\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMGQ5YTM1NmMtYmIxYy00N2VmLWJhZTYtN2EwYTY3MWFhOTczXkEyXkFqcGdeQXVyNTA2NTI0MTY#._V1_SX300.jpg\"},{\"Title\":\"The Lego Batman Movie\",\"Year\":\"2017\",\"imdbID\":\"tt4116284\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTcyNTEyOTY0M15BMl5BanBnXkFtZTgwOTAyNzU3MDI#._V1_SX300.jpg\"},{\"Title\":\"Batman: The Animated Series\",\"Year\":\"1992–1995\",\"imdbID\":\"tt0103359\",\"Type\":\"series\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BOTM3MTRkZjQtYjBkMy00YWE1LTkxOTQtNDQyNGY0YjYzNzAzXkEyXkFqcGdeQXVyOTgwMzk1MTA#._V1_SX300.jpg\"},{\"Title\":\"Batman: Under the Red Hood\",\"Year\":\"2010\",\"imdbID\":\"tt1569923\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BNmY4ZDZjY2UtOWFiYy00MjhjLThmMjctOTQ2NjYxZGRjYmNlL2ltYWdlL2ltYWdlXkEyXkFqcGdeQXVyNTAyODkwOQ##._V1_SX300.jpg\"},{\"Title\":\"Batman: The Dark Knight Returns, Part 1\",\"Year\":\"2012\",\"imdbID\":\"tt2313197\",\"Type\":\"movie\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMzIxMDkxNDM2M15BMl5BanBnXkFtZTcwMDA5ODY1OQ##._V1_SX300.jpg\"}]", new TypeReference<ArrayList<YourClass>>() {});
for (YourClass yourClass: yourClassList) {
System.out.println(yourClass);
}
}
P.S: Keep in your mind that you must not remove brackets [] from your JSON as you said in your question.

Related

How to add an object to an arraylist in a method

I want to write a method that adds a Phone to an ArrayList.
Phone class:
public class Phone {
private int id;
private String brand;
private String model;
private int cameraResolution;
public Phone(int id, String brand, String model, int cameraResolution) {
this.id=id;
this.brand=brand;
this.model=model;
this.cameraResolution= cameraResolution;
}
public void showDetails() {
System.out.println("id "+ this.id);
System.out.println("Marka to "+ this.brand);
System.out.println("Model to "+ this.model);
System.out.println("Rozdzielczosc aparatu to " + this.cameraResolution);
}
#Override
public String toString() {
return "Brand: " + this.brand + ", Model: " + this.model + ", Camera Resolution: " + this.cameraResolution + ", Id: " + this.id;
}
}
Shop class:
import java.util.ArrayList;
public class Shop {
private String name;
private ArrayList<Phone> phones;
private ArrayList<Tv> tvs;
public Shop(String name, ArrayList<Phone> phones, ArrayList<Tv> tvs ) {
this.name=name;
this.phones=phones;
this.tvs=tvs;
}
public ArrayList<Phone> addNewPhone(Phone newPhone) {
return phones.add(this.newPhone); // this doesnt work
}
}
Main class:
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Phone galaxy= new Phone(1, "Samsung","galaxy",12);
Phone lumia= new Phone(2, "Nokia","lumia",13);
Phone pixel= new Phone(3, "Google","pixel",14);
Phone[] phones = new Phone[3];
phones[0]= galaxy;
phones[1]= lumia;
phones[2]= pixel;
for (Phone phone: phones) {
phone.showDetails();
}
System.out.println(lumia.toString());
Client client1= new Client(1, "Jan", "Kowalski", null);
Client client2= new Client(1, "Magda", "Nowak", null);
}
}
I know that I need to return an ArrayList<Phone> and I need to receive a type of Phone in this method, then it should return list of new phones, but I don't know why it's not working.
Eclipse shows this error : newPhone cannot be resolved or is not a filed.
You have to problems in your method addNewPhone:
Probably do not want to add the field newPhones of the class Shop (because you don't have that field) but the method parameter of that name.
And none of the ArrayList.add overloads returns the list itself. As I don't see a single call of the addNewPhone method I can't really judge it, but I would think twice if you really need to return that list there
I would write it like this:
public addNewPhone(Phone newPhone) {
phones.add(newPhone);
}
If you need to return the phones list, I would always only use List<Phone> and never ArrayList, and probably also return Collections.unmodifiableList(phones)

HashMap Issuses

Edited the getTypeString method in the Flowers class now I just get the pointer to the object
I'm working on a project for one of my classes. I haven't worked with HashMap before and I need to use one. In this java class I'm trying to print out the full description that I have set. But it wont print the HashMap value from the key. I have tried to use some code from my book, but with no luck.
This is the class that is calling the class that has the HashMap:
public class Garden
{
private Gardener gardener;
private Tools tools;
private Flowers flowers;
/**
* Constructor for objects of class Garden
*/
public Garden()
{
gardener = new Gardener();
tools = new Tools();
Flowers rose;
rose = new Flowers("a beautiful red flower");
rose.setFlower("red", rose);
System.out.println(rose.fullDescription());
}
}
Edited the getTypeString method
This is the class that is using the HashMap:
import java.util.Set;
import java.util.HashMap;
public class Flowers
{
private String fDescription;
private HashMap<String, Flowers> flowers;
/**
* Constructor for objects of class Flowers
*/
public Flowers(String fDescription)
{
this.fDescription = fDescription;
flowers = new HashMap<String, Flowers>();
}
public void setFlower(String color, Flowers type)
{
flowers.put(color, type);
}
public String flowerDescription()
{
return fDescription;
}
public String fullDescription()
{
return "The "+ getTypeString() + " is " + fDescription;
}
private String getTypeString()
{
String des = "";
Collection<Flowers> vals = flowers.values();
for(Flowers f : vals){
des += f;
}
return des;
}
}
The problem, I think, is in the getTypeString() function. Can anyone point me in the right direction?
Edit
I removed the getTypeString method and edited the fullDescription method:
public String fullDescription()
{
return "The "+ type + " is " + fDescription;
}
now I'm trying to get the 'HashMap' to print the objects like so:
"Flower [type= type, description= Description "]"
using thes methods:
public static void printHashMap()
{
System.out.println("hashmap: " + flowers);
}
#Override
public String toString()
{
return "Flower [type=" + type + ", description=" + fDescription ]";
}
From your post, what I have understood is that you want to print the description of flowers. So I think you can try something like:
private String getTypeString(){
String des = "";
Collection<String> vals = flowers.values();
for(String f : vals){
des = des + f.flowerDescription();
}
return des;
}
Override the toString method in your class
Declare a toString method with the following modifiers and return type:
#Override
public String toString() {
return this.fDescription;
}
Implement the method so that it returns a string.

Constructing an object from a string

Is it possible to construct an object given a string, toString() method, and the Class itself.
For example we have class Book.
class Book
{
// ...
String getTitle()
{
return title;
}
String getPubYear()
{
return pubYear;
}
void setTitle(String _title)
{
title = _title;
}
void setPubYear(String _pubYear)
{
pubYear = _pubYear;
}
public String toString(){
return title+" "+pubYear;
}
}
If we have the String:
"ExampleTitle 2017"
How can we create an instance of the class Book, with which has attribute:
title=ExampleTitle
pubyear=2017
We can do the following:
Book book = new Book();
String exampleString = "ExampleTitle 2017";
String[] parts = exampleString.split();
book.setTitle(parts[0]);
book.setPubYear(parts[1]);
But this is long winded. Is there a more automatic way to do this?
You can add a new constructor:
public Book(String s) {
String[] parts = s.split(" ");
if (parts.length() == 1) {
this.title = s;
} else {
this.title=parts[0];
this.pubYear(Integer.parseInt(parts[1]));
}
}
You should add NumberFormatException handling on your own but I recommend my post about it.
The above constructor will take a String, split it by a space and perform what you have done. You can use it like:
Book book = new Book("Example_title 2001");
but it's not the best approach. You should rather use standard patterns and first extract the values you want to set to your Book and then pass them to the constructor.
The good way of doing what you want will be to make another constructor:
public class Book {
public Book(String s, int y) {
this.title = s;
this.year = y;
}
}
Please change year field to int or long. Year shouldn't be a String as long as you're not using Roman numbers.

Constructor with Field from another class is undefined?

I'm tasked by a newbie Java tutorial to do the below
In the user class:
Create a method called readBook(Book book)
readBook should print, "<User> read <title>"
In the BookRunner
For each book, create an author.
Separately, create another user and call the readBook method on that user, passing in one of the created books
The below is my code:
public class Ex1_BookRunner {
public static void main(String[] args) {
Book firstBook = new Book("One Piece", "Oda-Sensei", 100, 123456);
Book secondBook = new Book("Life of Megan Fox", "Micheal Bay", 200, 928765);
}
}
public class User {
public String name;
public int age;
public String location;
public Book title;
public String toString() {
String description1 = "Name:" + name + " Age:"+ age + " Location:" + location;
return description1;
}
public void readBook(Book book) {
System.out.println(name + " read " + title.title);
}
}
public class Book {
public String title;
public User author;
public int numPages;
public int isbn;
public Book(String title, User author, int numPages, int isbn) {
this.title = title;
this.author = author;
this.numPages = numPages;
this.isbn = isbn;
}
public String toString() {
String description = "Title:" + title + "Author"+ author.name + "Num. of pages" + numPages + "ISBN" + isbn;
return description;
}
}
I'm having problems even understanding what the question wants me to do. I've got the below questions
What does the question mean by getting me to print <User> read <title> with the readBook method? Did I interpret the question correctly with the way I set up the readBook method?
What should be the correct code in the method?
I have problems getting the author created, as I get the error The constructor Book(String, String, int, int) is undefined and the Eclipse IDE wants me to change the constructor in Book from (String, User, int, int) to (String, String, int, int). Experiments with User."Oda-Sensei", "Oda-Sensei".name, "Oda-Sensei.User" all give me the notice that the variable I'm introducing cannot be resolved.
From the questioning, it sounds like authors are users. Your constructor calls in the main method are passing in strings, hence your error about the constructor. If authors are users, then you should change your calls from:
public static void main(String[] args) {
Book firstBook = new Book("One Piece", "Oda-Sensei", 100, 123456);
Book secondBook = new Book("Life of Megan Fox", "Micheal Bay", 200, 928765);
}
to
public static void main(String[] args) {
User odaSensei = new User();
odaSensei.name = "Oda-Sensei";
User michaelBay = new User();
michaelBay.name = "Michael Bay";
Book firstBook = new Book("One Piece", odaSensei, 100, 123456);
Book secondBook = new Book("Life of Megan Fox", michaelBay, 200, 928765);
}
Be sure to set the other variables of the authors The other option is to change the type of authors to String, in which case the main method will not have the change.
I'd also recommend adding a constructor for Users, so that you can just initialize all of the variables from the new call.
The second part "Separately, create another user and call the readBook method on that user, passing in one of the created books"
Is telling you to create a brand new user, e.g. bob
User bobUser = new User();
bobUser.name="Bob";
and then take this new user and have him read one of the books:
bobUser.readBook(firstBook);
The goal is to get the read book to print out:
Bob read One Piece
To do this, you'll need to change the readBook method from:
public void readBook(Book book) {
System.out.println(name + " read " + title.title);
}
to:
public void readBook(Book book) {
System.out.println(name + " read " + book.title);
}

How to return a private variable

Ok so I'm trying to get a better understanding of how to return a private variable from a class that I have created. I've only provided a small snippet of my main program to explain my question, so if more information is needed please let me know. My goal is to return a string from the class (working great), but also be able to return the private variables individually as needed (example used below is "flight_number").
public class Flights {
private String dest_city, dest_state, departureDate, departureTime;
private int flight_number;
public Flights(String city, String state, String dDate, String dTime, int flightNumber) {
dest_city = city;
dest_state = state;
departureDate = dDate;
departureTime = dTime;
flight_number = flightNumber;
}
public String toString() {
return "Flight number: " + flight_number + " Destination: " + dest_city + "," + dest_state + " Departing on:" + departureDate + " at" + departureTime + ".";
}
}
public class dummy {
public static void main(String[] args) {
// Uses the constructor to set values
Flights flight1 = new Flights("Houston", "Texas", "12/20/2014", "12:40 pm", 100);
System.out.println(flight1);
System.out.println(flight_number); // Error: `flight_number` cannot be resolved to a variable.
}
}
You need to add a public getter in Flights and call it from main:
public class Flights {
// all the private fields
public int getFlightNumber() {
return this.flight_number;
}
}
In Main:
public static void main(String[] args) {
Flights flight1 = new Flights("Houston", "Texas"); //...
System.out.println(flight1);
System.out.println(flight1.getFlightNumber()); // call the getter
}
You should start with an editor like eclipse and that should help you get started quickly. Getters and Setters is what you need, but start with Eclipse and you should do better.

Categories

Resources