Jude Fernandes
Jude Fernandes

Reputation: 7527

Unable to read data from object using gson and retrofit

The server currently returns a json which looks like the json given below, it contains a field called data which is an array of arrays with each array having multiple objects and each object having a key called item_type. The key item_type allows me to figure out exactly what type of object it is so that I can cast it accordingly in java but I am unable to read the item_type field.

{  
   "page":1,
   "data":[  
      [  
         {  
            "id":1,
            "name":"xyz",
            "item_type":1
         }
      ],
      [  
         {  
            "cid":1,
            "item_type":2
         }
      ],
      [  
         {  
            "item":1,
            "item_type":3
         }
      ]
   ]
}

The retrofit interface is like so

    @GET("Search")
        Observable<SearchResults> search(@Query(ParamsHolder.GET_QUERY) 
    String query, @Query(ParamsHolder.GET_PAGE) int page);

where the SearchResults class looks like this

public class SearchResults {

    int page;

    List<List<Object>> data;

    public int getPage() {
        return page;
    }

    public List<List<Object>> getData() {
        return data;
    }
}

I am able to fetch the data fine but I need to read the objects that are inside each list. In order to do that I used the following code


public class SearchItem {

  int item_type;

  public int getItemType() {
      return item_type;
  }
}

List<List<Object>> data = objects.getData();

for (int i = 0; i < data.size(); i++) {

  List<Object> list = data.get(i);

  for (int j = 0; j < list.size(); j++) {

    SearchItem item = (SearchItem) list.get(i);

    Log.d("search", " json=" + list.get(j).toString());
    Log.d("search", " item=" + item.toString() + " type=" + item.getItemType());
    }

}

I created a dummy SearchItem class which I assumed would let me typecast the Object type so I could read the item_type which would let me know exactly the type of object this is.

It throws an error com.google.gson.internal.LinkedTreeMap cannot be cast to in.example.models.SearchItem

The end goal here it to be able to cast each object in the array to the correct type and the only way I can do that is by reading the item_type key in the object

Upvotes: 2

Views: 133

Answers (2)

has19
has19

Reputation: 1317

use Response as a return type in your interface retrofit function as shown below

@GET("Search")
Observable<Response<ResponseBody>> search(@Query(ParamsHolder.GET_QUERY) 
              String query, @Query(ParamsHolder.GET_PAGE) int page);

this way you can retrieve the full json body and you have now full control on how parse the data based on item_type

so basically you call function response.body().string() to get the json body

and than you parse manually like shown below:

 JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(response.body().string());
            JSONArray jsonArray = jsonObject.getJSONArray("data");

            //looping through the data array 
            for(int i = 0;i<jsonArray.length();i++){
                JSONArray  childArr = jsonArray.getJSONArray(i);
             //looping through current child array inside data 
                  for(int j = 0;j<childArr .length();j++){
                   JSONObject nestedChildObj =childArr.getJSONObject(j);
                   //now i have access to item_type
                   int item_type =  nestedChildObj .getInt("item_type")
                   //now you can use gson to parse the nestedChildObj based 
                   //on item_type or manually do the parsing
                 }
            }


        } catch (JSONException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

Upvotes: 1

Roshaan Farrukh
Roshaan Farrukh

Reputation: 399

Use Gson to directly parse the response

Update SearchResults

 public class SearchResults {

    int page;

    List<List<SearchItem>> data;

    public int getPage() {
        return page;
    }

    public List<List<SearchItem>> getData() {
        return data;
    }
}

You can access item_type like this

searchResult.getData.get(i).get(0).item_type

Upvotes: 1

Related Questions