java 如何在 Retrofit 库中使用 Gson?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32490011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 20:16:51  来源:igfitidea点击:

How I can use Gson in Retrofit library?

javaandroidjsongsonretrofit

提问by mohammad tofi

I used Retrofit for send request and receive the response in android but have problem when I want convert response which come from the sever it is always give me Exception:

我使用 Retrofit 发送请求并在 android 中接收响应,但是当我想要转换来自服务器的响应时遇到问题,它总是给我Exception

retrofit.RetrofitError: com.google.gson.JsonSyntaxException: 
               java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING

When response from server should give me list from movies so I need put all this movies in list.

当服务器的响应应该给我电影列表时,我需要将所有这些电影都放在列表中。

Movie(Model Class):

Movie(模型类):

public class Movie {
    public Movie() {}
    @SerializedName("original_title")
    private String movieTitle;
    @SerializedName("vote_average")
    private String movieVoteAverage;
    @SerializedName("overview")
    private String movieOverview;
    ............  
}

GitMovieApiClass:

GitMovieApi班级:

public interface GitMovieApi {
    @GET("/3/movie/{movie}")  
    public void getMovie(@Path("movie") String typeMovie,@Query("api_key") String  keyApi, Callback<Movie> response);    
}

RestAdapterconfiguration:

RestAdapter配置:

RestAdapter restAdapter = new RestAdapter.Builder()
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .setConverter(new GsonConverter(new GsonBuilder().registerTypeAdapter(Movie.class, new UserDeserializer()).create()))
                    .setEndpoint("http://api.themoviedb.org")
                    .build(); 
                     GitMovieApi git = restAdapter.create(GitMovieApi.class);  
                git.getMovie("popular", "Keyapi", new Callback<Movie>() {
                @Override
                public void success(Movie movie, Response response) {
                    Toast.makeText(getActivity(), "s", Toast.LENGTH_LONG).show();
                }
                @Override
                public void failure(RetrofitError error) {
                    Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
                }
            });

UserDeserializer:

用户解串器:

public class UserDeserializer implements JsonDeserializer<Movie> {
        @Override
        public Movie deserialize(JsonElement jsonElement, Type typeOF,
                                 JsonDeserializationContext context)
                throws JsonParseException {
            JsonElement userJson = new JsonParser().parse("results");
            return new Gson().fromJson(userJson, Movie.class);
        }
    }    

Json(Response):

JSON(响应):

{
  "page": 1,
  "results": [
    {
      "adult": false,
      "backdrop_path": "/tbhdm8UJAb4ViCTsulYFL3lxMCd.jpg",
      "genre_ids": [
        53,
        28,
        12
      ],
      "id": 76341,
      "original_language": "en",
      "original_title": "Mad Max: Fury Road",
      "overview": "An apocalyptic story set in the furthest.",
      "release_date": "2015-05-15",
      "poster_path": "/kqjL17yufvn9OVLyXYpvtyrFfak.jpg",
      "popularity": 48.399601,
      "title": "Mad Max: Fury Road",
      "video": false,
      "vote_average": 7.6,
      "vote_count": 2114
    },
    {
      "adult": false,
      "backdrop_path": "/sLbXneTErDvS3HIjqRWQJPiZ4Ci.jpg",
      "genre_ids": [
        10751,
        16,
        12,
        35
      ],
      "id": 211672,
      "original_language": "en",
      "original_title": "Minions",
      "overview": "Minions Stuart.",
      "release_date": "2015-06-25",
      "poster_path": "/s5uMY8ooGRZOL0oe4sIvnlTsYQO.jpg",
      "popularity": 31.272707,
      "title": "Minions",
      "video": false,
      "vote_average": 6.8,
      "vote_count": 1206
    },     
],
  "total_pages": 11871,
  "total_results": 237415
}  

采纳答案by durron597

You don't even need to make a custom deserializer here.

您甚至不需要在这里制作自定义解串器。

Get rid of UserDeserializerentirely, it's not needed. Your query is returning a list of movies, so make your callback to an object that actually reads the list of movies:

UserDeserializer完全摆脱,它不需要。您的查询正在返回电影列表,因此请对实际读取电影列表的对象进行回调:

public class MovieList {
    @SerializedName("results")
    List<Movie> movieList;
    // you can also add page, total_pages, and total_results here if you want
}

Then your GitMovieApiclass would be:

那么你的GitMovieApi班级将是:

public interface GitMovieApi {
    @GET("/3/movie/{movie}")  
    public void getMovie(@Path("movie") String typeMovie,
                @Query("api_key") String keyApi,
                Callback<MovieList> response);    
}

Your RestAdapter:

你的RestAdapter

RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setConverter(new GsonConverter(new GsonBuilder()).create()))
                .setEndpoint("http://api.themoviedb.org")
                .build(); 
                 GitMovieApi git = restAdapter.create(GitMovieApi.class); 

The problem is notthat you have written the Deserializerincorrectly (although, you have, but it's okay because you don't need it, JsonParseris nothow you do it), but the default deserialization behavior should work just fine for you. Use the above code and it will work just fine.

问题在于您写错了Deserializer(虽然,您有,但没关系,因为您不需要它,JsonParser不是您如何做),但默认的反序列化行为应该适合您。使用上面的代码,它会工作得很好。

回答by bendaf

In Retrofit 2 it is even simpler. Your GitMovieApiclass:

在 Retrofit 2 中,它甚至更简单。你的GitMovieApi班级:

interface MoviesApi {
    @GET("/3/movie/{movie}")
    Call<MovieList> getMovies(@Path("movie") String typeMovie,
                              @Query("api_key") String keyApi);
}

And than you just need to create a Retrofit object, and make a callback:

而不是您只需要创建一个 Retrofit 对象,并进行回调:

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(MOVIES_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
service = retrofit.create(MoviesApi.class);

Call<MovieList> mlc = service.getMovies(getArguments().getString(ARG_MOVIE_TYPE), getString(R.string.THE_MOVIE_DB_API_TOKEN));
mlc.enqueue(new Callback<MovieList>() {
        @Override
        public void onResponse(Call<MovieList> call, Response<MovieList> response) {
            movies = response.body().movieList;
        }

        @Override
        public void onFailure(Call<MovieList> call, Throwable t) {}
});