SIDDHARTH SINGH
SIDDHARTH SINGH

Reputation: 137

Android Retrofit nested JSON objects in arraylist

I am using PokeApi to create an android app. I am using Retrofit library to parse data. My API looks like this:

{
  "abilities": [2 items],
  "base_experience": 64,
  "forms": [1 item],
  "game_indices": [20 items],
  "height": 7,
  "held_items": [],
  "id": 1,
  "is_default": true,
  "location_area_encounters": "https://pokeapi.co/api/v2/pokemon/1/encounters",
  "moves": [78 items],
  "name": "bulbasaur",
  "order": 1,
  "past_types": [], 
  "species": {2 items},
  "sprites": {10 items},
  "weight": 69,
  "stats": [
    {
    "base_stat": 45,
    "effort": 0,
    "stat": {
       "name": "hp",
       "url": "https://pokeapi.co/api/v2/stat/1/"
     }
   },
   {
   "base_stat": 49,
   "effort": 0,
   "stat": {
     "name": "attack",
     "url": "https://pokeapi.co/api/v2/stat/2/"
    }
   },
   .
   ....

}

I am able to log values like name, weight and height but unable to get the items as array which is inside the value stats. Also I need stat (name and url) which is nested inside stats. Here is what I did. These is my Model Classes.

public class PokeDetail {

    private String name;
    private String height;
    private String weight;

    @SerializedName("stats")
    @Expose
    private List<PokeStats> stats = null;

    public List<PokeStats> getStats() {
        return stats;
    }

    public void setStats(List<PokeStats> stats) {
        this.stats = stats;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getHeight() {
        return height;
    }

    public void setHeight(String height) {
        this.height = height;
    }

    public String getWeight() {
        return weight;
    }

    public void setWeight(String weight) {
        this.weight = weight;
    }

}

public class PokeStats {

    private String effort;

    public String getEffort() {
        return effort;
    }

    public void setEffort(String effort) {
        this.effort = effort;
    }

}

Here is what my MainActivity looks like:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://pokeapi.co/api/v2/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        PokeApiService pokeApiService = retrofit.create(PokeApiService.class);

        Call<PokeDetail> call = pokeApiService.getPokeDetails(pokeNum);

        call.enqueue(new Callback<PokeDetail>() {
            @Override
            public void onResponse(Call<PokeDetail> call, Response<PokeDetail> response) {
                if(!response.isSuccessful()){
                    Log.i("ERROR", "onResponse: " + response.code());
                }

                PokeDetail pokeDetails = response.body();
                Log.i("NAME", pokeDetails.getName());
                Log.i("Height", pokeDetails.getHeight());
                Log.i("Weight", pokeDetails.getWeight());
                List<PokeStats> p = pokeDetails.getStats();
                Log.i("ListDATA", p.toString());

            }

            @Override
            public void onFailure(Call<PokeDetail> call, Throwable t) {
                Log.i("ERROR", t.getMessage());
            }
        });

And here is my output: enter image description here

Upvotes: 0

Views: 555

Answers (1)

Mayur Gajra
Mayur Gajra

Reputation: 9073

Log not proper Issue

What you're seeing is the default version of toString if you want to have log in your way then override it. See the example class below.

I need stat (name and url) which is nested inside stat

You need to have stat key inside your PokeStats class.

Example:

public class PokeStats {

    @SerializedName("base_stat")
    @Expose
    private Integer baseStat;
    @SerializedName("effort")
    @Expose
    private Integer effort;
    @SerializedName("stat")
    @Expose
    private Stat stat;

    public Integer getBaseStat() {
        return baseStat;
    }

    public void setBaseStat(Integer baseStat) {
        this.baseStat = baseStat;
    }

    public Integer getEffort() {
        return effort;
    }

    public void setEffort(Integer effort) {
        this.effort = effort;
    }

    public Stat getStat() {
        return stat;
    }

    public void setStat(Stat stat) {
        this.stat = stat;
    }


    @Override
    public String toString() {
        return "PokeStats{" +
                "baseStat=" + baseStat +
                ", effort=" + effort +
                ", stat=" + stat.toString() +
                '}';
    }
}

& the nested Stat class:

public class Stat {

    @SerializedName("name")
    @Expose
    private String name;
    @SerializedName("url")
    @Expose
    private String url;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    @Override
    public String toString() {
        return "Stat{" +
                "name='" + name + '\'' +
                ", url='" + url + '\'' +
                '}';
    }
}

Suggestion:

If you need to make classes for such bug response you can just use online tools like this one: https://www.jsonschema2pojo.org/

Enter your response & selection JSON, GSON such options accordingly & just generate classes.

Upvotes: 1

Related Questions