简体   繁体   中英

Retrofit - How to get response from JSON objects

I need to get a list of reviews using Retrofit from the following api query:

http://api.themoviedb.org/3/movie/{id}/reviews?api_key=#######

The JSON returned is:

{"id":83542,"page":1,"results":[{"id":"51910979760ee320eb020fc2","author":"Andres Gomez","content":"Interesting film with an exceptional cast, fantastic performances and characterizations. The story, though, is a bit difficult to follow and, in the end, seems to not have a real point.","url":"https://www.themoviedb.org/review/51910979760ee320eb020fc2"},{"id":"520a8d10760ee32c8718e6c2","author":"Travis Bell","content":"Cloud Atlas was a very well made movie but unlike most of the \"simultaneous stories that all come together at the end\" type of movies, this one just didn't. I'm still unclear as to the point of it all.\r\n\r\nAnother issue I had was a general feeling of goofiness. Sure, the Cavendish story was pure comedy but the rest of the stories just didn't feel serious enough to me.\r\n\r\nIt carried my attention for the 172 minutes well enough and it was entertaining. I just expected more of a pay off at the end.\r\n\r\nAll in all, it's definitely worth seeing but I still haven't made up my mind if I truly liked it or not. What did you think?","url":"https://www.themoviedb.org/review/520a8d10760ee32c8718e6c2"}],"total_pages":1,"total_results":2}

My goal is to to access the "content" attribute and then put in a TextView.

Where I am having trouble is, for some reason I cannot figure out how to return a list of result objects from the above JSON and then access the content attribute using getContent().

I think there may be a problem with the way I am using my model object/s? Should they be two seperate objects? I'm not sure. When I try to print out the objects I get empty responses...

Any help would be great.

Retrofit interface code is:

 public class MovieService {
    public interface MovieDbApi {

    @GET("/3/movie/{id}?&append_to_response=reviews")
    Call<MovieReview> getReviews(
            @Path("id") int id,
            @Query("api_key") String apiKey);

    }
}

Model object code is:

POJO 1

public class MovieReview {

@SerializedName("id")
@Expose
private int id;
@SerializedName("page")
@Expose
private int page;

@SerializedName("results")
@Expose
private List<MovieReviewDetail> results = new ArrayList<MovieReviewDetail>();
@SerializedName("total_pages")
@Expose
private int totalPages;
@SerializedName("total_results")
@Expose
private int totalResults;

/**
 *
 * @return
 * The id
 */
public int getId() {
    return id;
}

/**
 *
 * @param id
 * The id
 */
public void setId(int id) {
    this.id = id;
}

/**
 *
 * @return
 * The page
 */
public int getPage() {
    return page;
}

/**
 *
 * @param page
 * The page
 */
public void setPage(int page) {
    this.page = page;
}

/**
 *
 * @return
 * The results
 */
public List<MovieReviewDetail> getResults() {
    return results;
}

/**
 *
 * @param results
 * The results
 */
public void setResults(List<MovieReviewDetail> results) {
    this.results = results;
}

/**
 *
 * @return
 * The totalPages
 */
public int getTotalPages() {
    return totalPages;
}

/**
 *
 * @param totalPages
 * The total_pages
 */
public void setTotalPages(int totalPages) {
    this.totalPages = totalPages;
}

/**
 *
 * @return
 * The totalResults
 */
public int getTotalResults() {
    return totalResults;
}

/**
 *
 * @param totalResults
 * The total_results
 */
public void setTotalResults(int totalResults) {
    this.totalResults = totalResults;
}

}

POJO 2

public class MovieReviewDetail {

@SerializedName("id")
@Expose
private int id;
@SerializedName("author")
@Expose
private String author;
@SerializedName("content")
@Expose
private String content;
@SerializedName("url")
@Expose
private String url;

/**
 *
 * @return
 * The id
 */
public int getId() {
    return id;
}

/**
 *
 * @param id
 * The id
 */
public void setId(int id) {
    this.id = id;
}

/**
 *
 * @return
 * The author
 */
public String getAuthor() {
    return author;
}

/**
 *
 * @param author
 * The author
 */
public void setAuthor(String author) {
    this.author = author;
}

/**
 *
 * @return
 * The content
 */
public String getContent() {
    return content;
}

/**
 *
 * @param content
 * The content
 */
public void setContent(String content) {
    this.content = content;
}

/**
 *
 * @return
 * The url
 */
public String getUrl() {
    return url;
}

/**
 *
 * @param url
 * The url
 */
public void setUrl(String url) {
    this.url = url;
}

}

Fragment code:

private static final String API_KEY = "#####";
private static final String API_BASE_URL_MOVIES = "http://api.themoviedb.org/";

private Call<MovieReview> call;
private MovieReview movieReview;
private List <MovieReviewDetail>  movieReviewDetails;

public void getMovieReview(int id){

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(API_BASE_URL_MOVIES)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    MovieService.MovieDbApi movieDbApi = retrofit.create(MovieService.MovieDbApi.class);

    call = movieDbApi.getReviews(id, API_KEY);

    call.enqueue(new Callback<MovieReview>() {
        @Override
        public void onResponse(Response<MovieReview> response) {
            if (!response.isSuccess()) {
                Log.d(LOG_TAG, "Error");
            }

            movieReview = response.body();
            movieReviewDetails = movieReview.getResults();

//Print out results 

for (int i = 0; i < movieReviewDetails.size(); i++) {
                System.out.println(movieReviewDetails.get(i).getContent());
            }

        }

        @Override
        public void onFailure(Throwable t) {

            Log.e("Throwable: ", t.getMessage());

        }
    });

}


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);

    getMovieReview(83542);
}

I don't know why people type incorrect JSON response and then expect problems not to happen. Did you even bother to post the entire JSON response this is the response you get.

{"adult":false,"backdrop_path":"/2ZA03KiD4jePTNBTJjGGFTNQPMA.jpg","belongs_to_collection":null,"budget":102000000,"genres":[{"id":18,"name":"Drama"},{"id":878,"name":"Science Fiction"}],"homepage":"http://cloudatlas.warnerbros.com/","id":83542,"imdb_id":"tt1371111","original_language":"en","original_title":"Cloud Atlas","overview":"A set of six nested stories spanning time between the 19th century and a distant post-apocalyptic future. Cloud Atlas explores how the actions and consequences of individual lives impact one another throughout the past, the present and the future. Action, mystery and romance weave through the story as one soul is shaped from a killer into a hero and a single act of kindness ripples across centuries to inspire a revolution in the distant future.  Based on the award winning novel by David Mitchell. Directed by Tom Tykwer and the Wachowskis.","popularity":3.552761,"poster_path":"/8VNiyIp67ZxhpNgdrwACW0jgvP2.jpg","production_companies":[{"name":"Anarchos Productions","id":450},{"name":"X-Filme Creative Pool","id":1972},{"name":"Ascension Pictures","id":7829},{"name":"ARD Degeto Film","id":10947},{"name":"Cloud Atlas Productions","id":11080},{"name":"Five Drops","id":11082},{"name":"Media Asia Group","id":11083},{"name":"Dreams of Dragon Picture","id":19621}],"production_countries":[{"iso_3166_1":"DE","name":"Germany"},{"iso_3166_1":"HK","name":"Hong Kong"},{"iso_3166_1":"SG","name":"Singapore"},{"iso_3166_1":"US","name":"United States of America"}],"release_date":"2012-10-26","revenue":130482868,"runtime":172,"spoken_languages":[{"iso_639_1":"en","name":"English"}],"status":"Released","tagline":"Everything is Connected","title":"Cloud Atlas","video":false,"vote_average":6.4,"vote_count":1774,"reviews":{"page":1,"results":[{"id":"51910979760ee320eb020fc2","author":"Andres Gomez","content":"Interesting film with an exceptional cast, fantastic performances and characterizations. The story, though, is a bit difficult to follow and, in the end, seems to not have a real point.","url":"https://www.themoviedb.org/review/51910979760ee320eb020fc2"},{"id":"520a8d10760ee32c8718e6c2","author":"Travis Bell","content":"Cloud Atlas was a very well made movie but unlike most of the \"simultaneous stories that all come together at the end\" type of movies, this one just didn't. I'm still unclear as to the point of it all.\r\n\r\nAnother issue I had was a general feeling of goofiness. Sure, the Cavendish story was pure comedy but the rest of the stories just didn't feel serious enough to me.\r\n\r\nIt carried my attention for the 172 minutes well enough and it was entertaining. I just expected more of a pay off at the end.\r\n\r\nAll in all, it's definitely worth seeing but I still haven't made up my mind if I truly liked it or not. What did you think?","url":"https://www.themoviedb.org/review/520a8d10760ee32c8718e6c2"}],"total_pages":1,"total_results":2}}

Notice the fact that that you can't directly access the inner object. Your outer object is reviews . You must then create a POJO class depicting that.

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

/**
 * Created by Ramandeep Singh on 17-03-2016.
 */
public class Reviews {
    @SerializedName("reviews")
    @Expose
private MovieReview reviews;

    public Reviews() {
    }


    public MovieReview getReviews() {
        return reviews;
    }

    public void setReviews(MovieReview reviews) {
        this.reviews = reviews;
    }
}

And furthermore, the ID is not Integer, it is string field.

Next time onwards type the correct and whole JSON response.

This is the method. After modification to service and utility

 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_BASE_URL_MOVIES)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        MovieService.MovieDbApi movieDbApi = retrofit.create(MovieService.MovieDbApi.class);

        call = movieDbApi.getReviews(id, API_KEY);

        call.enqueue(new Callback<Reviews>() {
                         @Override
                         public void onResponse(Call<Reviews> call, Response<Reviews> response) {
                             if (!response.isSuccessful()) {
                                 System.out.println("Error");
                             }

                             reviews = response.body();
                             movieReview=reviews.getReviews();
                             movieReviewDetails = movieReview.getResults();

//Print out results

                             for (int i = 0; i < movieReviewDetails.size(); i++) {
                                 System.out.println(movieReviewDetails.get(i).getContent());
                             }

                         }

                         @Override
                         public void onFailure(Call<Reviews> call, Throwable t) {
                             t.printStackTrace();

                         }
                     }
      );

This is your service now.

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;

/**
 * Created by Ramandeep Singh on 17-03-2016.
 */
public class MovieService {
    public interface MovieDbApi {

        @GET("/3/movie/{id}?&append_to_response=reviews")
        Call<Reviews> getReviews(
                @Path("id") int id,
                @Query("api_key") String apiKey);

    }
}

This is the output you get.

Interesting film with an exceptional cast, fantastic performances and characterizations. The story, though, is a bit difficult to follow and, in the end, seems to not have a real point.
Cloud Atlas was a very well made movie but unlike most of the "simultaneous stories that all come together at the end" type of movies, this one just didn't. I'm still unclear as to the point of it all.

Another issue I had was a general feeling of goofiness. Sure, the Cavendish story was pure comedy but the rest of the stories just didn't feel serious enough to me.

It carried my attention for the 172 minutes well enough and it was entertaining. I just expected more of a pay off at the end.

All in all, it's definitely worth seeing but I still haven't made up my mind if I truly liked it or not. What did you think?

Give this a try, Instead of seperating get call and get call with enqueue.

call = movieDbApi.getReviews(id, API_KEY).enqueue(new Callback<MovieReview>() {
        @Override
        public void onResponse(Response<MovieReview> response) {
            if (!response.isSuccess()) {
                Log.d(LOG_TAG, "Error");
            }

            movieReview = response.body();
            movieReviewDetails = movieReview.getResults();

//Print out results 

for (int i = 0; i < movieReviewDetails.size(); i++) {
                System.out.println(movieReviewDetails.get(i).getContent());
            }

        }

        @Override
        public void onFailure(Throwable t) {

            Log.e("Throwable: ", t.getMessage());

        }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM