【问题标题】:Parse Json array with multiple objects using retrofit 2 in android在android中使用retrofit 2解析具有多个对象的Json数组
【发布时间】:2016-10-26 05:41:19
【问题描述】:

我在我的项目中使用改造 2 来实现网络功能,我能够解析来自服务器的 json 对象响应,但现在我应该解析一个看起来像这样的 json 数组

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

这是来自服务器的响应,我为响应创建了这个 POJO

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

    }
   }
}

我的 pojo 是对的吗? 我的问题是,我无法解析此响应。任何帮助将不胜感激。 提前致谢

编辑: 这是我对服务器的请求(使用 rest api)

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

编辑 2:按照 Niko Adrianus Yuwono 的建议,我已将代码更改为 List。

这是新的变化

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

这是来自服务器的响应

D/Assets:资产 id_asset bb:1 D/Assets:资产 id_category bb:1 D/Assets:资产名称 bb:Samsung Galaxy 6 D/Assets:资产状态 bb : 1 10-26 13:13:17.898 22784-22784/ D/AndroidRuntime: 关机 VM 10-26 13:13:17.898 22784-22784/E/AndroidRuntime:致命异常: 主进程:,PID:22784 java.lang.NullPointerException:尝试 调用虚拟方法'java.lang.Double .api.model.AssetResponse$AssetRate.getValue()' 在空对象上 参考
.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(本机方法)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

每当我访问内部对象时,它都会抛出上述错误

【问题讨论】:

  • 你正在解析一个数组,所以你的改造响应应该是 Call> getAssessList()
  • 好的,我试过了,但我只能解析 json 数组的第一个字符串,不能触及内部的 json 对象。怎么做?你能给我举个例子吗
  • 将您的课程私有 AssetRate 更改为 Public
  • @SudheeshR 您应该将您的内部类访问权限更改为 public 以便 GSON 可以看到内部类的 setter 和 getter,有关更多详细信息,请参阅我的答案
  • 在答案中添加了一个解决方案检查它@SudheeshR

标签: java android json retrofit2


【解决方案1】:

您的 POJO 看起来不错,但您的 JSON 响应是 JSONArray,因此您需要将其声明为对象列表而不是对象

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

并且您需要将您的内部类访问权限更改为 public,以便 GSON 可以看到该类的 setter 和 getter。

【讨论】:

  • 我改为 > 但我无法访问内部对象,错误提示 org.json.JSONException: Value at 0 is null.
  • 为什么我不能访问内部的 json 对象?你对此有什么想法吗?请分享
【解决方案2】:

您的 Json 键值数据正在从一个索引更改为另一个索引。

错误的 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,
}
]

我在 github 上与您的 json 共享了一个完整的项目。 https://github.com/lingarajsankaravelu/retrofit2v.git

改造代码应该像我在问题评论中提到的那样。

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

正如您要求解释您的 pojo 类中的更改,它应该是这样的。

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

像上面那样分离你的内部类。如果您正在处理一个大型项目,分离您的内部类模型将很有用。您不必再次编写相同的 pojo 类。您可以改用这个单独的类结构。

【讨论】:

  • 我以前使用过单独的课程,但我遇到了同样的问题。所以我认为这不是关于分离课程。
  • @SudheeshR,答案就在这里
  • 我已经让我的api开发人员更改类型冲突,我会在后端更改后更新。非常感谢@HourGlass。
  • 如果更新的 api 有效,我肯定会接受这个答案。我认为这将是合理的。我感谢你的努力。
  • 非常感谢,你救了我。
【解决方案3】:

您可以使用这个站点来生成 POJO 类。只需输入您的 JSON 响应并选择您使用的 JSON 类型,例如 GSON、Jackson.etc。你得到完美的 POJO 课程。无需更改任何内容。

http://www.jsonschema2pojo.org/

【讨论】:

  • 我收到了回复,请参阅 json 的问题。但我无法访问其中的 json 对象。值返回 null。我不知道为什么。但我能够解析数组的第一个键值对。这是真正的问题。
【解决方案4】:

你的改造界面应该是

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

并确保您的 变量名称与 JSON 响应上的键相同 或者您可以为此使用注释 @SerializedName 并且为了简化您可以使用 JSON 来POJO在线转换器:http://www.jsonschema2pojo.org/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 2018-04-15
    相关资源
    最近更新 更多