3

I'm using retrofit 2 for networking functions in my project, and I'm able to parse the json object responses from the server but now I'm supposed to parse a json array that look like this

[
    {
        "id_asset": 1,
        "id_category": 1,
        "id_brand": 2,
        "name": "Samsung Galaxy 6",
        "status": 1,
        "updated_at": "Oct 3, 2016 10:24:28 AM",
        "rank": 1,
        "rate": {
            "id_asset_rate": 2,
            "id_asset": 1,
            "value": 5000,
            "loan_to_value": 50,
            "offered": 2500,
            "annual_rate": 3,
            "quantity": 5,
            "created_at": "Oct 23, 2016 5:31:31 AM",
            "updated_at": "Oct 23, 2016 5:32:31 AM"
        },
        "best_rate": {
            "id_asset": "1",
            "value": "5000",
            "loan_to_value": "50",
            "offered": "2500",
            "annual_rate": "3",
            "quantity": "5",
            "rank": "1"
        },
        "category": {
            "id_category": 1,
            "id_parent": 0,
            "name": "Mobile Phones",
            "image": "",
            "sort": 1,
            "status": 1,
            "created_at": null,
            "updated_at": null,
            "_links": {
                "self": {
                    "href": "/v1/categories/1"
                }
            }
        },
        "brand": {
            "id_brand": 2,
            "name": "Samsung",
            "status": 1,
            "created_at": null,
            "updated_at": null
        },
        "_links": {
            "self": {
                "href": "/v1/assets/1"
            }
        }
    },
    {
        "id_asset": 2,
        "id_category": 1,
        "id_brand": 1,
        "name": "i Phone 5",
        "status": 1,
        "updated_at": "Oct 3, 2016 8:04:36 AM",
        "rank": false,
        "rate": null,
        "best_rate": false,
        "category": {
            "id_category": 1,
            "id_parent": 0,
            "name": "Mobile Phones",
            "image": "",
            "sort": 1,
            "status": 1,
            "created_at": null,
            "updated_at": null,
            "_links": {
                "self": {
                    "href": "/v1/categories/1"
                }
            }
        },
        "brand": {
            "id_brand": 1,
            "name": "Apple",
            "status": 1,
            "created_at": null,
            "updated_at": null
        },
        "_links": {
            "self": {
                "href": "/v1/assets/2"
            }
        }
    }
]

This is the response from the server and I created this POJO for the response

public class AssetResponse {
    private Integer id_asset;
    private Integer id_category;
    private Integer id_brand;
    private String  name;
    private Integer status;
    private String updated_at;

    private AssetRate assetRate;
    private AssetCategory assetCategory;
    private Links links;
    private Self self;
    private AssetBrand assetBrand;
    private HasLinked hasLinked;


    public Integer getId_asset() {
        return id_asset;
    }

    public void setId_asset(Integer id_asset) {
        this.id_asset = id_asset;
    }

    public Integer getId_category() {
        return id_category;
    }

    public void setId_category(Integer id_category) {
        this.id_category = id_category;
    }

    public Integer getId_brand() {
        return id_brand;
    }

    public void setId_brand(Integer id_brand) {
        this.id_brand = id_brand;
    }

    public String getName() {
        return name;
    }

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

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getUpdated_at() {
        return updated_at;
    }

    public void setUpdated_at(String updated_at) {
        this.updated_at = updated_at;
    }

    public AssetRate getAssetRate() {
        return assetRate;
    }

    public void setAssetRate(AssetRate assetRate) {
        this.assetRate = assetRate;
    }

    public AssetCategory getAssetCategory() {
        return assetCategory;
    }

    public void setAssetCategory(AssetCategory assetCategory) {
        this.assetCategory = assetCategory;
    }

    public Links getLinks() {
        return links;
    }

    public void setLinks(Links links) {
        this.links = links;
    }

    public Self getSelf() {
        return self;
    }

    public void setSelf(Self self) {
        this.self = self;
    }

    public AssetBrand getAssetBrand() {
        return assetBrand;
    }

    public void setAssetBrand(AssetBrand assetBrand) {
        this.assetBrand = assetBrand;
    }

    public HasLinked getHasLinked() {
        return hasLinked;
    }

    public void setHasLinked(HasLinked hasLinked) {
        this.hasLinked = hasLinked;
    }

    private class AssetRate {

        private Integer id_asset_rate;
        private Integer id_asset;
        private Double value;
        private Double loan_to_value;
        private Double offered;
        private Double annual_rate;
        private String updated_at;

        public Integer getId_asset_rate() {
            return id_asset_rate;
        }

        public void setId_asset_rate(Integer id_asset_rate) {
            this.id_asset_rate = id_asset_rate;
        }

        public Integer getId_asset() {
            return id_asset;
        }

        public void setId_asset(Integer id_asset) {
            this.id_asset = id_asset;
        }

        public Double getValue() {
            return value;
        }

        public void setValue(Double value) {
            this.value = value;
        }

        public Double getLoan_to_value() {
            return loan_to_value;
        }

        public void setLoan_to_value(Double loan_to_value) {
            this.loan_to_value = loan_to_value;
        }

        public Double getOffered() {
            return offered;
        }

        public void setOffered(Double offered) {
            this.offered = offered;
        }

        public Double getAnnual_rate() {
            return annual_rate;
        }

        public void setAnnual_rate(Double annual_rate) {
            this.annual_rate = annual_rate;
        }

        public String getUpdated_at() {
            return updated_at;
        }

        public void setUpdated_at(String updated_at) {
            this.updated_at = updated_at;
        }
    }

    private class AssetCategory {

        private Integer id_category;
        private Integer id_parent;
        private String name;
        private String image;
        private Integer sort;
        private Integer status;
        private String created_at;
        private String updated_at;

        private Links links;


        public Integer getId_category() {
            return id_category;
        }

        public void setId_category(Integer id_category) {
            this.id_category = id_category;
        }

        public Integer getId_parent() {
            return id_parent;
        }

        public void setId_parent(Integer id_parent) {
            this.id_parent = id_parent;
        }

        public String getName() {
            return name;
        }

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

        public String getImage() {
            return image;
        }

        public void setImage(String image) {
            this.image = image;
        }

        public Integer getSort() {
            return sort;
        }

        public void setSort(Integer sort) {
            this.sort = sort;
        }

        public Integer getStatus() {
            return status;
        }

        public void setStatus(Integer status) {
            this.status = status;
        }

        public String getCreated_at() {
            return created_at;
        }

        public void setCreated_at(String created_at) {
            this.created_at = created_at;
        }

        public String getUpdated_at() {
            return updated_at;
        }

        public void setUpdated_at(String updated_at) {
            this.updated_at = updated_at;
        }

        public Links getLinks() {
            return links;
        }

        public void setLinks(Links links) {
            this.links = links;
        }
    }

    private class Links {
        @SerializedName("self")
        @Expose
        private Self self;

        /**
         *
         * @return
         * The self
         */
        public Self getSelf() {
            return self;
        }

        /**
         *
         * @param self
         * The self
         */
        public void setSelf(Self self) {
            this.self = self;
        }
    }

    private class Self {
        @SerializedName("href")
        @Expose
        private String href;

        /**
         *
         * @return
         * The href
         */
        public String getHref() {
            return href;
        }

        /**
         *
         * @param href
         * The href
         */
        public void setHref(String href) {
            this.href = href;
        }


    }

    private class AssetBrand {


        private Integer id_brand;
        private String name;
        private Integer status;
        private String created_at;
        private String updated_at;

        public Integer getId_brand() {
            return id_brand;
        }

        public void setId_brand(Integer id_brand) {
            this.id_brand = id_brand;
        }

        public String getName() {
            return name;
        }

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

        public Integer getStatus() {
            return status;
        }

        public void setStatus(Integer status) {
            this.status = status;
        }

        public String getCreated_at() {
            return created_at;
        }

        public void setCreated_at(String created_at) {
            this.created_at = created_at;
        }

        public String getUpdated_at() {
            return updated_at;
        }

        public void setUpdated_at(String updated_at) {
            this.updated_at = updated_at;
        }


    }

    private class HasLinked {

        private Integer has_linked;

        private Links links;

        public Integer getHas_linked() {
            return has_linked;
        }

        public void setHas_linked(Integer has_linked) {
            this.has_linked = has_linked;
        }

        public Links getLinks() {
            return links;
        }

        public void setLinks(Links links) {
            this.links = links;
        }

    }
   }
}

Is my pojo is right ? My problem is, I can't parse this response. Any help will be appreciated. Thanks in advance

EDIT : This is my request to server (using rest api)

@GET("url")
Call<AssetResponse> getAssetList();

EDIT 2: I've changed the code to List, as suggested by Niko Adrianus Yuwono.

This is the new changes

    private void getAssets() {

        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(logging);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constants.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient.build())
                .build();

        final ApiInterface apiInterface = retrofit.create(ApiInterface.class);

        final AssetRequest assetRequest = new AssetRequest();
        assetRequest.setAcc_tok(ACCESS_TOKEN);

        final Call<List<AssetResponse>> assetList = apiInterface.getAssetList();

        assetList.enqueue(new Callback <List<AssetResponse>>() {

            @Override
            public void onResponse(Call<List<AssetResponse>> call, Response<List<AssetResponse>> response) {
                int statusCode = response.code();

                List<AssetResponse> assetResponseList = response.body();

                if (statusCode == 200) {

                  for (int i = 0; i < assetResponseList.size(); i++ ){
                        Integer id_asset = assetResponseList.get(i).getId_asset();
                        Integer id_category = assetResponseList.get(i).getId_category();
                        Integer status = assetResponseList.get(i).getStatus();
                        String name = assetResponseList.get(i).getName();
                        Log.d("Assets ","Asset id_asset  bb : " + id_asset);
                        Log.d("Assets ","Asset id_category  bb : " + id_category);
                        Log.d("Assets ","Asset name  bb : " + name);
                        Log.d("Assets ","Asset status  bb : " + status);

                        Double val = assetResponseList.get(i).getAssetRate().getValue();
                        Log.d("val ","val is : " +val);

                    }
                } else {
                    Toast.makeText(getContext(), "network error " + statusCode, Toast.LENGTH_LONG).show();

   }
  }

@Override
public void onFailure(Call<List<AssetResponse>> call, Throwable t) {

       Log.d("Asset GET Failure", "onFailure: " + t.getMessage());
      //showProgress(false);
    }
 });
}

and this is the response from the server

D/Assets: Asset id_asset bb : 1 D/Assets: Asset id_category bb : 1 D/Assets: Asset name bb : Samsung Galaxy 6 D/Assets: Asset status bb : 1 10-26 13:13:17.898 22784-22784/ D/AndroidRuntime: Shutting down VM 10-26 13:13:17.898 22784-22784/ E/AndroidRuntime: FATAL EXCEPTION: main Process: , PID: 22784 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Double .api.model.AssetResponse$AssetRate.getValue()' on a null object reference
.AssetDatabaseFragment$2.onResponse(AssetDatabaseFragment.java:133)
retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68) android.os.Handler.handleCallback(Handler.java:739)
android.os.Handler.dispatchMessage(Handler.java:95)
android.os.Looper.loop(Looper.java:148)
android.app.ActivityThread.main(ActivityThread.java:5417)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Whenever I access the inner objects it throws error like the above

13
  • 2
    you are parsing an array right so your retrofit response should be Call<List<AssetReponse>> getAssessList() Commented Oct 26, 2016 at 5:47
  • ok, i've tried that, but im only able to parse the first strings of json array, and can't touch the inner json objects. How to do that? Can you please give me an example for the above Commented Oct 26, 2016 at 5:53
  • 1
    change your class private AssetRate to Public Commented Oct 26, 2016 at 6:13
  • 1
    @SudheeshR You should change your inner class access to public so GSON can see the setter and getter of the inner class, see my answer for more detail Commented Oct 26, 2016 at 6:16
  • added a solution in answers check it @SudheeshR Commented Oct 26, 2016 at 7:55

4 Answers 4

2

Your POJO looks right, but your JSON response is a JSONArray so you need to declare it as a List of Objects rather than an Object

@GET("url")
Call<List<AssetResponse>> getAssetList();

And you need to change your inner class access to public so GSON can see the setter and getter of that class.

Sign up to request clarification or add additional context in comments.

2 Comments

I changed to <List<AssetResponse>> but I couldnt access the inner object, error says org.json.JSONException: Value at 0 is null.
Why I cant access the inner json objects? Do you have any idea about this? Please share
1

Your Json key value data is changing from one index to another.

Wrong Json:

[{
//Make this either integer or boolean
 "rank": 1,
// best rate is object here in the next index, it's treated as boolean. 
  "best_rate": {
            "id_asset": "1",
            "value": "5000",
            "loan_to_value": "50",
            "offered": "2500",
            "annual_rate": "3",
            "quantity": "5",
            "rank": "1"
        }

},
{
"rank":false,
"best_rate":false,
}
]

I have a complete project shared on github with your json. https://github.com/lingarajsankaravelu/retrofit2v.git

Retrofit code should be like this as i mentioned in the question comment.

@GET("url")
Call<List<AssetResponse>> getAssetList();

As you have requested to explain the changes in your pojo class it should be like this.

AssetReponse.class:

public class AssetResponse {
    private Integer id_asset;
    private Integer id_category;
    private Integer id_brand;
    private String  name;
    private Integer status;
    private String updated_at;

    private AssetRate assetRate;
    private AssetCategory assetCategory;
    private Links links;
    private Self self;
    private AssetBrand assetBrand;
    private HasLinked hasLinked;


    public Integer getId_asset() {
        return id_asset;
    }

    public void setId_asset(Integer id_asset) {
        this.id_asset = id_asset;
    }

    public Integer getId_category() {
        return id_category;
    }

    public void setId_category(Integer id_category) {
        this.id_category = id_category;
    }

    public Integer getId_brand() {
        return id_brand;
    }

    public void setId_brand(Integer id_brand) {
        this.id_brand = id_brand;
    }

    public String getName() {
        return name;
    }

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

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getUpdated_at() {
        return updated_at;
    }

    public void setUpdated_at(String updated_at) {
        this.updated_at = updated_at;
    }

    public AssetRate getAssetRate() {
        return assetRate;
    }

    public void setAssetRate(AssetRate assetRate) {
        this.assetRate = assetRate;
    }

    public AssetCategory getAssetCategory() {
        return assetCategory;
    }

    public void setAssetCategory(AssetCategory assetCategory) {
        this.assetCategory = assetCategory;
    }

    public Links getLinks() {
        return links;
    }

    public void setLinks(Links links) {
        this.links = links;
    }

    public Self getSelf() {
        return self;
    }

    public void setSelf(Self self) {
        this.self = self;
    }

    public AssetBrand getAssetBrand() {
        return assetBrand;
    }

    public void setAssetBrand(AssetBrand assetBrand) {
        this.assetBrand = assetBrand;
    }

    public HasLinked getHasLinked() {
        return hasLinked;
    }

    public void setHasLinked(HasLinked hasLinked) {
        this.hasLinked = hasLinked;
    }
}

AssetRate.class

public class AssetRate {

        private Integer id_asset_rate;
        private Integer id_asset;
        private Double value;
        private Double loan_to_value;
        private Double offered;
        private Double annual_rate;
        private String updated_at;

        public Integer getId_asset_rate() {
            return id_asset_rate;
        }

        public void setId_asset_rate(Integer id_asset_rate) {
            this.id_asset_rate = id_asset_rate;
        }

        public Integer getId_asset() {
            return id_asset;
        }

        public void setId_asset(Integer id_asset) {
            this.id_asset = id_asset;
        }

        public Double getValue() {
            return value;
        }

        public void setValue(Double value) {
            this.value = value;
        }

        public Double getLoan_to_value() {
            return loan_to_value;
        }

        public void setLoan_to_value(Double loan_to_value) {
            this.loan_to_value = loan_to_value;
        }

        public Double getOffered() {
            return offered;
        }

        public void setOffered(Double offered) {
            this.offered = offered;
        }

        public Double getAnnual_rate() {
            return annual_rate;
        }

        public void setAnnual_rate(Double annual_rate) {
            this.annual_rate = annual_rate;
        }

        public String getUpdated_at() {
            return updated_at;
        }

        public void setUpdated_at(String updated_at) {
            this.updated_at = updated_at;
        }
    }

Seperate your inner class like above. Seperating your inner class model will be useful if you are working on a large project. where you don't have to write the same pojo class again. you can use this seperate class structure instead.

5 Comments

I was used separate classes before but I faced the same problem. So its not about separating the classes I think.
@SudheeshR, The answer is here
I've asked my api developer to change the type conflict, I'll update after the changes in backend. Thanks a lot @HourGlass.
I'll definitely accept this answer if the updated api works. I think it would be reasonable. And I appreciate your efforts.
Thank you very much, you saved me.
0

You can use this site to generate POJO class. Just enter your JSON response and choose which JSON type you using like GSON,Jackson.etc. and You get perfect POJO classes. no need to change anything.

http://www.jsonschema2pojo.org/

1 Comment

I'm getting the response, refer the question for the json. But I could not access the json objects in it. values are returning null. I dont know why. But I'm able to parse the very first key value pairs of the array. This is the real problem.
0

Your Retrofit interface should be

@GET("url") Call<List<AssetReponse>> getAssessList();

And make sure that your variable name same with key on JSON Response Or you can use annotation @SerializedName for that & for make it simple you can use JSON to POJO Online converter : http://www.jsonschema2pojo.org/

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.