Retrofit возвращает ноль для значения из ключа JSON, хотя у него есть ответ Android - PullRequest
0 голосов
/ 03 июля 2019

У меня есть ответ JSON, как это.

{
  "movies": [
    {
      "Title": "Avengers:Age of Ultron ",
      "Year": "2015 ",
      "Rated": "PG-13 ",
      "Released": "01 May 2015 ",
      "Runtime": "141 min ",
      "Genre": "Action, Adventure, Sci-Fi ",
      "Director": "Joss Whedon ",
      "Writer": "Joss Whedon, Stan Lee (based on the Marvel comics by), Jack Kirby (based on the Marvel comics by), Joe Simon (character created by: Captain America), Jack Kirby (character created by: Captain America), Jim Starlin (character created by: Thanos) ",
      "Actors": "Robert Downey Jr., Chris Hemsworth, Mark Ruffalo, Chris Evans ",
      "Plot": "When Tony Stark and Bruce Banner try to jump-start a dormant peacekeeping program called Ultron, things go horribly wrong and it's up to Earth's mightiest heroes to stop the villainous Ultron from enacting his terrible plan. ",
      "Language": "English, Korean ",
      "Country": "USA ",
      "Awards": "7 wins \u0026 45 nominations."
    },
    {
      "Title": "TheAvengers ",
      "Year": "2012 ",
      "Rated": "PG-13 ",
      "Genre": "Action, Adventure, Sci-Fi ",
      "Actors": "Robert Downey Jr., Chris Evans, Mark Ruffalo, Chris Hemsworth ",
      "Plot": "Earth's mightiest heroes must come together and learn to fight as a team if they are going to stop the mischievous Loki and his alien army from enslaving humanity. ",
      "Language": "English, Russian, Hindi ",
      "Country": "USA ",
      **"Poster": "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg ",**
      "Released": "04 May 2012 ",
      "Runtime": "143 min ",
      "Director": "Joss Whedon ",
      "Writer": "Joss Whedon (screenplay), Zak Penn (story), Joss Whedon (story) ",
      "Awards": "Nominated for 1 Oscar. Another 38 wins \u0026 79 nominations. "
    },
    {
      "Title": "Sleepless ",
      "Year": "2017 ",
      "Rated": "R ",
      "Released": "13Jan 2017 ",
      "Runtime": "95 min ",
      "Genre": "Action, Crime, Thriller ",
      "Director": "Baran bo Odar ",
      "Writer": "Andrea Berloff (screenplay by), Frédéric Jardin (based on the film    Nuit blanche written by), Nicolas Saada (based on the film Nuit blanche written by), Olivier Douyère (based on the film    Nuit blanche   written by)",
      "Actors": "Jamie Foxx, Michelle Monaghan, Scoot McNairy, Dermot Mulroney ",
      "Plot": "A cop with a connection to the criminal underworld scours a nightclub in search of his kidnapped son. ",
      "Language": "English ",
      "Country": "USA ",
      "Awards": "1 nomination. ",
      **"Poster ": "https://m.media-amazon.com/images/M/MV5BNjEwMDAyOTM4OV5BMl5BanBnXkFtZTgwMzc4MjMyMDI@._V1_SX300.jpg "**
    },
    {
      "Title": "TheDark Knight ",
      "Year": "2008 ",
      "Rated": "PG-13 ",
      "Released": "18 Jul 2008 ",
      "Runtime": "152 min ",
      "Genre": "Action, Crime, Drama ",
      "Director": "Christopher Nolan ",
      "Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters) ",
      "Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine ",
      "Plot": "When the menace known as the Joker emerges from his mysterious past, he wreaks havoc and chaos on the people of Gotham. The Dark Knight must accept one of the greatest psychological and physical tests of his ability to fight injustice. ",
      "Language": "English, Mandarin ",
      "Country": "USA, UK ",
      "Awards": "Won 2 Oscars. Another 152 wins \u0026 155 nominations. ",
      **"Poster ": "https://m.media-amazon.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg "**
    },
    {
      "Title": "SavingPrivate Ryan ",
      "Year": "1998 ",
      "Rated": "R ",
      "Released": "24 Jul 1998 ",
      "Runtime": "169 min ",
      "Genre": "Drama, War ",
      "Director": "Steven Spielberg ",
      "Writer": "Robert Rodat ",
      "Actors": "Tom Hanks, Tom Sizemore, Edward Burns, Barry Pepper ",
      "Plot": "Following the Normandy Landings, a group of U.S. soldiers go behind enemy lines to retrieve a paratrooper whose brothers have been killed in action. ",
      "Language": "English, French, German, Czech ",
      "Country": "USA ",
      "Awards": "Won 5 Oscars. Another 74 wins \u0026 74 nominations. ",
      **"Poster ": "https://m.media-amazon.com/images/M/MV5BZjhkMDM4MWItZTVjOC00ZDRhLThmYTAtM2I5NzBmNmNlMzI1XkEyXkFqcGdeQXVyNDYyMDk5MTU@._V1_SX300.jpg "**
    },
    {
      "Plot": "Moirac, a notary, and Landron, a retired army surgeon, who have been friends since boyhood, live in the same village. The daughter of the notary is, at the same time, the god-child of the...",
      "Title": "Fatherand God Father ",
      "Year": "1912 ",
      "Rated": "N/A ",
      "Released": "27 Feb 1913 ",
      "Runtime": "N/A ",
      "Genre": "Short, Comedy ",
      "Director": "N/A ",
      "Writer": "N/A ",
      "Actors": "N/A ",
      "Language": "French ",
      "Country": "France ",
      "Awards": "N/A ",
      **"Poster ": "N/A ",**
      "Ratings ": "",
      "Metascore ": "N/A ",
      "imdbRating ": "N/A ",
      "imdbVotes ": "N/A ",
      "imdbID ": "tt1318958 ",
      "Type ": "movie ",
      "DVD ": "N/A ",
      "BoxOffice ": "N/A ",
      "Production ": "N/A ",
      "Website ": "N/A ",
      "Response ": "True "
    }

В приведенном выше ответе json вы можете видеть, что ключ json «Постер» отсутствует в первом наборе данных, тогда как во втором наборе данных он присутствует, аналогично для некоторых он равен нулю.

Теперь проблема в том, что когда я использую в Retrofit только одни данные от Poster, они возвращаются, тогда как для всех остальных он отображается как null Проблема приходит только для Poster

Ниже класс, как я сделал.

public class Movies {
    @SerializedName("Released")
    private String Released;
    @SerializedName("Plot")
    private String Plot;
    @SerializedName("Director")
    private String Director;
    @SerializedName("Title")
    private String Title;
    @SerializedName("Actors")
    private String Actors;
    @SerializedName("Runtime")
    private String Runtime;
    @SerializedName("Awards")
    private String Awards;
    @SerializedName("Year")
    private String Year;
    @SerializedName("Language")
    private String Language;
    @SerializedName("Rated")
    private String Rated;
    @SerializedName("Country")
    private String Country;
    @SerializedName("Genre")
    private String Genre;
    @SerializedName("Writer")
    private String Writer;
    @SerializedName("Poster")
    @Expose
    private String Poster;

    public String getPoster() {
        return Poster;
    }

    public void setPoster(String Poster) {
        this.Poster = Poster;
    }

    public String getReleased() {
        return Released;
    }

    public void setReleased(String Released) {
        this.Released = Released;
    }

    public String getPlot() {
        return Plot;
    }

    public void setPlot(String Plot) {
        this.Plot = Plot;
    }

    public String getDirector() {
        return Director;
    }

    public void setDirector(String Director) {
        this.Director = Director;
    }

    public String getTitle() {
        return Title;
    }

    public void setTitle(String Title) {
        this.Title = Title;
    }

    public String getActors() {
        return Actors;
    }

    public void setActors(String Actors) {
        this.Actors = Actors;
    }

    public String getRuntime() {
        return Runtime;
    }

    public void setRuntime(String Runtime) {
        this.Runtime = Runtime;
    }

    public String getAwards() {
        return Awards;
    }

    public void setAwards(String Awards) {
        this.Awards = Awards;
    }

    public String getYear() {
        return Year;
    }

    public void setYear(String Year) {
        this.Year = Year;
    }

    public String getLanguage() {
        return Language;
    }

    public void setLanguage(String Language) {
        this.Language = Language;
    }

    public String getRated() {
        return Rated;
    }

    public void setRated(String Rated) {
        this.Rated = Rated;
    }

    public String getCountry() {
        return Country;
    }

    public void setCountry(String Country) {
        this.Country = Country;
    }

    public String getGenre() {
        return Genre;
    }

    public void setGenre(String Genre) {
        this.Genre = Genre;
    }

    public String getWriter() {
        return Writer;
    }

    public void setWriter(String Writer) {
        this.Writer = Writer;
    }

Выше приведен класс pojo, в котором я указал SerializedName для poster.

Сейчас в Retrofit,

public class MoviesRepository {
    private static MoviesRepository moviesRepository;
    private MovieApiInterface newsApi;
    public static Application application;

    public static MoviesRepository getInstance() {
        if (moviesRepository == null) {
            moviesRepository = new MoviesRepository(application);
        }
        return moviesRepository;
    }



    public MoviesRepository(Application application) {
        this.application = application;
        newsApi = RetrofitService.cteateService(MovieApiInterface.class);
    }

public MutableLiveData<MovieResponse> getMovieUpdates() {
    final MutableLiveData<MovieResponse> moviesData = new MutableLiveData<>();
    newsApi.getMovieDetails().enqueue(new Callback<MovieResponse>() {
        @Override
        public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
            if (response.isSuccessful()) {
                if(response.body()!=null) {
                    moviesData.setValue(response.body());
                }
            }

        }

        @Override
        public void onFailure(Call<MovieResponse> call, Throwable t) {
            Log.i("RETROFIT RESPONSE", "Failure"+call.toString());
            Log.i("RETROFIT RESPONSE", "Failure"+t);
           // moviesData.setValue(null);

        }
    });
    return moviesData;
}

Здесь, в ответ, когда я вижу, я получаю данные для первого, но для всех остальных ответов, плакат становится пустым.

Когда я отлаживаю и проверяю, (я не опубликовал полностью. Я взял только постер)

position 1:
Poster = "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg "
    position 2:
    Poster = null
    position 3: 
    Poster = null

Один постер становится нулевым для всех, кроме позиция 1. когда я проверил ответ.

MoviesResponse:

 public class MovieResponse implements Serializable {
    @SerializedName("movies")
    private List<Movies> movies;

    public List<Movies> getMovies() {
        return movies;
    }

    public void setMovies(List<Movies> movies) {
        this.movies = movies;
    }
}

MoviesViewModel:

 public class MoviesViewModel extends AndroidViewModel {
    private MutableLiveData<MovieResponse> mutableLiveData;
    private MoviesRepository moviesRepository;

    public MoviesViewModel(@NonNull Application application) {
        super(application);
        moviesRepository = new MoviesRepository(application);
    }

    public void init() {
        if (mutableLiveData != null) {
            return;
        }
        moviesRepository = MoviesRepository.getInstance();
        mutableLiveData = moviesRepository.getMovieUpdates();
    }

    public MutableLiveData<MovieResponse> getNewsRepository() {
        return moviesRepository.getMovieUpdates();
    }
}

RetrofitService:

public class RetrofitService {
    private static Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.myjson.com/bins/")
            .addConverterFactory(GsonConverterFactory.create())
            .build();


    public static <S> S cteateService(Class<S> serviceClass) {
        return retrofit.create(serviceClass);
    }
}



public class MoviesRepository {
    private static MoviesRepository moviesRepository;
    private MovieApiInterface newsApi;
    public static Application application;

    public static MoviesRepository getInstance() {
        if (moviesRepository == null) {
            moviesRepository = new MoviesRepository(application);
        }
        return moviesRepository;
    }



    public MoviesRepository(Application application) {
        this.application = application;
        newsApi = RetrofitService.cteateService(MovieApiInterface.class);
    }

    public MutableLiveData<MovieResponse> getMovieUpdates() {
        final MutableLiveData<MovieResponse> moviesData = new MutableLiveData<>();
        newsApi.getMovieDetails().enqueue(new Callback<MovieResponse>() {
            @Override
            public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
                if (response.isSuccessful()) {
                    if(response.body()!=null) {
                        moviesData.setValue(response.body());
                    }
                }

            }

            @Override
            public void onFailure(Call<MovieResponse> call, Throwable t) {
                Log.i("RETROFIT RESPONSE", "Failure"+call.toString());
                Log.i("RETROFIT RESPONSE", "Failure"+t);
               // moviesData.setValue(null);

            }
        });
        return moviesData;
    }
}

MainActivity:

public class MainActivity extends AppCompatActivity {
    MoviesAdapter newsAdapter;
    RecyclerView rvHeadline;
    MoviesViewModel newsViewModel;
    List<Movies> newsArticles;
    List<Movies> articleArrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rvHeadline = findViewById(R.id.rvNews);
         articleArrayList = new ArrayList<>();

        newsAdapter = new MoviesAdapter(MainActivity.this, articleArrayList);
        rvHeadline.setLayoutManager(new LinearLayoutManager(this));
        rvHeadline.setAdapter(newsAdapter);

        newsViewModel = ViewModelProviders.of(this).get(MoviesViewModel.class);
        newsViewModel.init();
        newsViewModel.getNewsRepository().observe(this, newsResponse -> {

            if (newsResponse != null) {
                newsArticles = newsResponse.getMovies();
                articleArrayList.addAll(newsArticles);
                for(int i=0;i<articleArrayList.size();i++){
                    String poster = articleArrayList.get(i).getPoster();
                    Log.i("poster","poster"+poster);
                }
                newsAdapter.notifyDataSetChanged();
            }
        });
       // setupRecyclerView();
    }

    private void setupRecyclerView() {
        if (newsAdapter == null) {
            newsAdapter = new MoviesAdapter(MainActivity.this, articleArrayList);
            rvHeadline.setLayoutManager(new LinearLayoutManager(this));
            rvHeadline.setAdapter(newsAdapter);
            rvHeadline.setItemAnimator(new DefaultItemAnimator());
            rvHeadline.setNestedScrollingEnabled(true);
        } else {
            newsAdapter.notifyDataSetChanged();
        }
    }
}

MoviesAdapter:

public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> {
    Context context;
    List<Movies> articles;

    public MoviesAdapter(Context context, List<Movies> articles) {
        this.context = context;
        this.articles = articles;
    }

    @NonNull
    @Override
    public MoviesAdapter.MoviesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.movies_item, parent, false);
        return new MoviesViewHolder(view);
    }
    @Override
    public void onBindViewHolder(@NonNull MoviesAdapter.MoviesViewHolder holder, final int position) {
        holder.tvName.setText(articles.get(position).getTitle());
        holder.tvDesCription.setText(articles.get(position).getPoster());
        String url = articles.get(position).getPoster();
        if(url!=null) {
           /* Glide.with(context) //passing context
                    .load(url) //passing your url to load image.
                    .dontAnimate()
                    .placeholder(context.getDrawable(R.drawable.ic_launcher_background)) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
                    .centerCrop()//this method help to fit image into center of your ImageView
                    .into(holder.ivNews);*/ //pass imageView reference to appear the image.*/
            Picasso.get()
                    .load(url)
                    .placeholder(R.drawable.ic_launcher_background)
                    .error(R.drawable.ic_launcher_background)
                    .into(holder.ivNews);
        }
    }
    @Override
    public int getItemCount() {
        return articles.size();
    }

    public class MoviesViewHolder extends RecyclerView.ViewHolder {

        TextView tvName;
        TextView tvDesCription;
        ImageView ivNews;

        public MoviesViewHolder(@NonNull View itemView) {
            super(itemView);

            tvName = itemView.findViewById(R.id.tvName);
            tvDesCription = itemView.findViewById(R.id.tvDesCription);
            ivNews = itemView.findViewById(R.id.ivNews);

        }
    }
}

Ответы [ 3 ]

0 голосов
/ 03 июля 2019

Вы можете обработать это, возвращая пустую строку по умолчанию или URL по умолчанию.См. Пример ниже.

В вашем классе модели вы должны это сделать.

@Expose
@SerializedName("Poster")
private String Poster;

public String getPoster() {
   return Poster == null ? "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg" : Poster;
}

public void setPoster(String Poster) {
   this.Poster = Poster;
}

В приведенном выше коде, если ваш ключ плаката не найден в json, выможет вернуть "" или URL по умолчанию .если ключ плаката найден в то время, он возвращает свое значение.

0 голосов
/ 03 июля 2019

Ключ «Плакат» содержит пробел."Плакат".Исправьте этот ключ JSON.

Ключ должен быть одинаковым для анализа.Вы пытаетесь разобрать "Плакат", но вы получаете "Плакат" и "Плакат".

0 голосов
/ 03 июля 2019

Я думаю, что некоторые из ваших объектов ответа не имеют этого ключа Poster, как первый объект в фрагменте примера.

...