Retrofit - 如何从JSON对象获取响应

时间:2022-03-06 00:12:45

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

我需要从以下api查询中使用Retrofit获取评论列表:

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

The JSON returned is:

返回的JSON是:

{"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.

我的目标是访问“content”属性,然后放入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().

我遇到问题的地方是,由于某种原因,我无法弄清楚如何从上面的JSON返回结果对象列表,然后使用getContent()访问content属性。

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

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

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);
}

2 个解决方案

#1


3  

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.

我不知道为什么人们输入不正确的JSON响应然后期望问题不会发生。您是否懒得发布整个JSON响应,这是您得到的响应。

{"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":"*"},{"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.

请注意,您无法直接访问内部对象。你的外部对象是评论。然后,您必须创建一个描述它的POJO类。

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.

而且,ID不是Integer,而是字符串字段。

Next time onwards type the correct and whole JSON response.

下次再输入正确的JSON响应。

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?

#2


0  

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

尝试一下,而不是分开get call并使用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());

        }
    });

#1


3  

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.

我不知道为什么人们输入不正确的JSON响应然后期望问题不会发生。您是否懒得发布整个JSON响应,这是您得到的响应。

{"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":"*"},{"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.

请注意,您无法直接访问内部对象。你的外部对象是评论。然后,您必须创建一个描述它的POJO类。

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.

而且,ID不是Integer,而是字符串字段。

Next time onwards type the correct and whole JSON response.

下次再输入正确的JSON响应。

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?

#2


0  

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

尝试一下,而不是分开get call并使用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());

        }
    });