Search code examples
androidjsonrx-javaretrofit

Fetch JSON data using retrofit and rxjava


I want to fetch json from a url https://api.myjson.com/bins/mxcsl/ using retrofit and rxjava. Sample json is this :

{
"data": [
{
  "itemId": "1",
  "desc": "Batcave",
  "audio": "https://storage.googleapis.com/a/17.mp3"
},
{
  "itemId": "2",
  "desc": "Fight Club rules",
  "audio": "https://storage.googleapis.com/a/2514.mp3"
},
{
  "itemId": "3",
  "desc": "Make an offer",
  "audio": "https://storage.googleapis.com/a/47.mp3"
}]}

And here is my code : Data Model :

public class Data {

private String itemId;
private String desc;
private String audio;

public String getItem() {
    return itemId;
}

public String getDesc() {
    return desc;
}

public String getAudio() {
    return audio;
}}

This is the Interface :

public interface RequestInterface {

@GET("/bins/mxcsl/")
Observable<List<Data>> register();

}

I'm loading something like this :

private void loadJSON() {


    RequestInterface requestInterface = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build().create(RequestInterface.class);

    mCompositeDisposable.add(requestInterface.register()
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(this::handleResponse,this::handleError));
}

private void handleResponse(List<Data> androidList) {

    mAndroidArrayList = new ArrayList<>(androidList);
    mAdapter = new DataAdapter(mAndroidArrayList);
    mRecyclerView.setAdapter(mAdapter);
}

private void handleError(Throwable error) {

    Toast.makeText(this, "Error "+error.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}

But Also I'm getting the error expected BEGIN_ARRAY but was BEGIN_OBJECT

I don't know where this is going wrong. Please help.


Solution

  • Your api response is a JSONObject which contain a JSONArray with key data.

    Wrap your List of Data with another Model class

    public class ResponseData {
    
      @SerializedName("data")
      private List<Data> dataList;
    
      public List<Data> getDataList() {
        return dataList;
      }
    
      public void setDataList(List<Data> list) {
        dataList = list;
      }
    
    }
    

    Use ResponseData class in RequestInterface

    public interface RequestInterface {
    
      @GET("/bins/mxcsl/")
      Observable<ResponseData> register();
    
    }
    

    Added:

    As your converted Response is ResponseData object so your handleResponse method parameter would be ResponseData type. In handleResponse get your expected list from getter method and set it to Adapter.

    handleResponse method

    private void handleResponse(ResponseData responseData) {
      if( responseData != null){
         List<Data> dataList = responseData.getDataList();
         mAndroidArrayList = new ArrayList<>();
         if(dataList!= null){
            mAndroidArrayList.addAll(dataList);
         }
         mAdapter = new DataAdapter(mAndroidArrayList);
         mRecyclerView.setAdapter(mAdapter);
     }
    }