0

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.

2
  • Because your json is not List<Data>. It's actually an object with the key data and that object is List<Data> Commented Jul 20, 2018 at 17:41
  • Possible duplicate of stackoverflow.com/q/9598707/9119277 Commented Jul 20, 2018 at 17:47

3 Answers 3

3

Your type

Observable<List<Data>> register();

is wrong. Because Json's first level is not Array (But object with field data, that is array). You should create class for outer structure

public class Outer{
    List<Data> data;
}

And specify in retrofit, as observable:

@GET("/bins/mxcsl/")
Observable<Outer> register();
Sign up to request clarification or add additional context in comments.

2 Comments

My handleResponse is this : private void handleResponse(List<Data> androidList) { mAndroidArrayList = new ArrayList<>(androidList); mAdapter = new DataAdapter(mAndroidArrayList); mRecyclerView.setAdapter(mAdapter); } How to change this ?
Like this, this will be your method: private void handleResponse(Outer response) inside it you can get list as: mAndroidArrayList = response.data And everything else will be the same
2

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);
 }
}

1 Comment

My handleResponse is this : private void handleResponse(List<Data> androidList) { mAndroidArrayList = new ArrayList<>(androidList); mAdapter = new DataAdapter(mAndroidArrayList); mRecyclerView.setAdapter(mAdapter); } How to change this ?
0

The error is because Retrofit is expecting a json array to be deserialized as a List

public interface RequestInterface {

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

But the json response is an object with a field named data that is an array

{
 "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"
}]}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.