【问题标题】:Android: Parsing a JSON array Inside of Another JSON ArrayAndroid:在另一个 JSON 数组中解析 JSON 数组
【发布时间】:2019-01-07 21:35:23
【问题描述】:

我是 JSON 解析的新手,我一直无法理解 JSONArrays 和 JSONObjects 以及如何浏览它们。我的应用程序解析 JSON 数据并将其显示在回收站视图中。 JSON 响应包含三个我想从中获取数据的 JSON 数组。办公室、官员和地址数组。这里的问题是地址数组在官方数组中,我不知道如何解析该数据。该应用程序适用于某些数据,但是当我尝试解析地址数组中的数据时,我从 logcat 中收到错误消息。这是整个 JSON 响应

   {
 "normalizedInput": {
  "line1": "2613 Irvington Avenue",
  "city": "San Bernardino",
  "state": "CA",
  "zip": "92407"
 },
 "offices": [
  {
   "name": "President of the United States",
   "levels": [
    "country"
   ],
   "roles": [
    "headOfState",
    "headOfGovernment"
   ]
  },
  {
   "name": "Vice-President of the United States",
   "levels": [
    "country"
   ],
   "roles": [
    "deputyHeadOfGovernment"
   ]
  },
  {
   "name": "United States Senate",
   "levels": [
    "country"
   ],
   "roles": [
    "legislatorUpperBody"
   ]
  },
  {
   "name": "United States House of Representatives CA-31",
   "levels": [
    "country"
   ],
   "roles": [
    "legislatorLowerBody"
   ]
  },
  {
   "name": "Governor",
   "levels": [
    "administrativeArea1"
   ],
   "roles": [
    "headOfGovernment"
   ]
  },
  {
   "name": "Lieutenant Governor",
   "levels": [
    "administrativeArea1"
   ],
   "roles": [
    "deputyHeadOfGovernment"
   ]
  },
  {
   "name": "City Treasurer"
  },
  {
   "name": "Mayor"
  },
  {
   "name": "City Attorney"
  },
  {
   "name": "City Clerk"
  },
  {
   "name": "Sheriff-Coroner"
  },
  {
   "name": "Auditor-Controller-Treasurer-Tax Collector"
  },
  {
   "name": "District Attorney"
  },
  {
   "name": "Assessor-Clerk-Recorder"
  },
  {
   "name": "San Bernardino County Superior Court Judge"
  },
  {
   "name": "CA State Assembly District 40"
  },
  {
   "name": "CA State Senate District 23"
  },
  {
   "name": "Board of Supervisors, District 5"
  },
  {
   "name": "Secretary of State"
  },
  {
   "name": "State Treasurer"
  },
  {
   "name": "Attorney General"
  },
  {
   "name": "State Superintendent of Public Instruction"
  },
  {
   "name": "State Controller"
  },
  {
   "name": "Insurance Commissioner"
  }
 ],
 "officials": [
  {
   "name": "Donald J. Trump",
   "address": [
    {
     "line1": "The White House",
     "line2": "1600 Pennsylvania Avenue NW",
     "city": "Washington",
     "state": "DC",
     "zip": "20500"
    }
   ],
   "party": "Republican",
   "phones": [
    "(202) 456-1111"
   ],
   "photoUrl": "https://www.whitehouse.gov/sites/whitehouse.gov/files/images/45/PE%20Color.jpg",
   "channels": [
    {
     "type": "GooglePlus",
     "id": "+whitehouse"
    },
    {
     "type": "Facebook",
     "id": "whitehouse"
    },
    {
     "type": "Twitter",
     "id": "potus"
    },
    {
     "type": "YouTube",
     "id": "whitehouse"
    }
   ]
  },
  {
   "name": "Mike Pence",
   "address": [
    {
     "line1": "The White House",
     "line2": "1600 Pennsylvania Avenue NW",
     "city": "Washington",
     "state": "DC",
     "zip": "20500"
    }
   ],
   "party": "Republican",
   "phones": [
    "(202) 456-1111"
   ],
   "photoUrl": "https://www.whitehouse.gov/sites/whitehouse.gov/files/images/45/VPE%20Color.jpg",
   "channels": [
    {
     "type": "GooglePlus",
     "id": "+whitehouse"
    },
    {
     "type": "Facebook",
     "id": "whitehouse"
    },
    {
     "type": "Twitter",
     "id": "VP"
    }
   ]
  },
  {
   "name": "Kamala D. Harris",
   "address": [
    {
     "line1": "112 Hart Senate Office Building",
     "city": "Washington",
     "state": "DC",
     "zip": "20510"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(202) 224-3553"
   ],
   "channels": [
    {
     "type": "Twitter",
     "id": "KamalaHarris"
    },
    {
     "type": "YouTube",
     "id": "UC0XBsJpPhOLg0k4x9ZwrWzw"
    }
   ]
  },
  {
   "name": "Dianne Feinstein",
   "address": [
    {
     "line1": "331 Hart Senate Office Building",
     "city": "Washington",
     "state": "DC",
     "zip": "20510"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(202) 224-3841"
   ],
   "photoUrl": "http://bioguide.congress.gov/bioguide/photo/F/F000062.jpg",
   "channels": [
    {
     "type": "Facebook",
     "id": "SenatorFeinstein"
    },
    {
     "type": "Twitter",
     "id": "SenFeinstein"
    },
    {
     "type": "YouTube",
     "id": "SenatorFeinstein"
    }
   ]
  },
  {
   "name": "Pete Aguilar",
   "address": [
    {
     "line1": "1223 Longworth House Office Building",
     "city": "Washington",
     "state": "DC",
     "zip": "20515"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(202) 225-3201"
   ],
   "photoUrl": "https://aguilar.house.gov/sites/aguilar.house.gov/files/styles/congress_image_medium/public/wysiwyg_uploaded/Headshot_0.jpg?itok=LSt7qkOV",
   "channels": [
    {
     "type": "Facebook",
     "id": "reppeteaguilar"
    },
    {
     "type": "Twitter",
     "id": "RepPeteAguilar"
    },
    {
     "type": "YouTube",
     "id": "UCIXCmfuRWrbgdTw257_lxJQ"
    },
    {
     "type": "YouTube",
     "id": "UCxwbFLOlKDsXrwizV5jah7g"
    }
   ]
  },
  {
   "name": "Edmund G. Brown Jr.",
   "address": [
    {
     "line1": "c/o State Capitol",
     "line2": "Suite 1173",
     "city": "Sacramento",
     "state": "CA",
     "zip": "95814"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(916) 445-2841"
   ],
   "channels": [
    {
     "type": "GooglePlus",
     "id": "+JerryBrown"
    },
    {
     "type": "Facebook",
     "id": "jerrybrown"
    },
    {
     "type": "Twitter",
     "id": "JerryBrownGov"
    }
   ]
  },
  {
   "name": "Gavin Newsom",
   "address": [
    {
     "line1": "State Capitol",
     "line2": "Suite 1114",
     "city": "Sacramento",
     "state": "CA",
     "zip": "95814"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(916) 445-8994"
   ],
   "photoUrl": "http://www.ltg.ca.gov/images/newsimages/i2.png",
   "emails": [
    "gavin@gavinnewsom.com"
   ],
   "channels": [
    {
     "type": "GooglePlus",
     "id": "+GavinNewsom"
    },
    {
     "type": "Facebook",
     "id": "GavinNewsom"
    },
    {
     "type": "Twitter",
     "id": "gavinnewsom"
    }
   ]
  },
  {
   "name": "David C. Kennedy",
   "address": [
    {
     "line1": "300 N. \"D\" Street",
     "line2": "2nd Floor",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92418"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(909) 384-5022"
   ]
  },
  {
   "name": "R. Carey Davis",
   "address": [
    {
     "line1": "300 N. \"D\" Street - 6th Floor",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92418"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(909) 384-5133"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "MayorCareyDavis"
    }
   ]
  },
  {
   "name": "Gary D. Saenz",
   "address": [
    {
     "line1": "300 N. \"D\" Street",
     "line2": "6th Floor",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92418"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(909) 384-5355"
   ],
   "emails": [
    "Attorney@sbcity.org"
   ]
  },
  {
   "name": "Georgeann \"Gigi\" Hanna",
   "address": [
    {
     "line1": "300 N. \"D\" Street",
     "line2": "2nd Floor",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92418"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(909) 384-5002"
   ]
  },
  {
   "name": "John McMahon",
   "address": [
    {
     "line1": "655 East Third Street",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92415"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(760) 956-5001"
   ],
   "emails": [
    "paffairs@sbcsd.org"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "sbcountysheriff"
    },
    {
     "type": "Twitter",
     "id": "sbcountysheriff"
    }
   ]
  },
  {
   "name": "Oscar Valdez",
   "address": [
    {
     "line1": "222 W. Hospitality Lane",
     "line2": "4th Floor",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92415"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(909) 382-7014"
   ]
  },
  {
   "name": "Michael Ramos",
   "address": [
    {
     "line1": "303 West 3rd Street",
     "line2": "6th Floor",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92415"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(909) 382-3669"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "SanBernardinoCountyDistrictAttorney"
    },
    {
     "type": "Twitter",
     "id": "sbcountyda"
    }
   ]
  },
  {
   "name": "Bob Dutton",
   "address": [
    {
     "line1": "First Floor",
     "line2": "222 W. Hospitality Lane",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92415"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(855) 732-2575"
   ]
  },
  {
   "name": "Denise Trager Dvorak",
   "party": "Nonpartisan"
  },
  {
   "name": "James C. Ramos",
   "address": [
    {
     "line1": "PO BOX 942849",
     "city": "Sacramento",
     "state": "CA",
     "zip": "94249"
    }
   ],
   "party": "Democratic Party",
   "phones": [
    "(916) 319-2040"
   ]
  },
  {
   "name": "Mike Morrell",
   "address": [
    {
     "line1": "STATE CAPITOL",
     "line2": "1303 10TH ST RM 3056",
     "city": "Sacramento",
     "state": "CA",
     "zip": "95814"
    }
   ],
   "party": "Republican",
   "phones": [
    "(909) 919-7731"
   ],
   "photoUrl": "http://senate.ca.gov/sites/senate.ca.gov/files/senator_photos/morrell-mike.jpg",
   "emails": [
    "senator.morrell@senate.ca.gov"
   ],
   "channels": [
    {
     "type": "Twitter",
     "id": "MikeMorrellGOP"
    },
    {
     "type": "Facebook",
     "id": "MikeMorrellGOP"
    }
   ]
  },
  {
   "name": "Josie Gonzales",
   "address": [
    {
     "line1": "385 N. Arrowhead Ave.",
     "line2": "5th Fl.",
     "city": "San Bernardino",
     "state": "CA",
     "zip": "92415"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(909) 387-4565"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "supervisorgonzales"
    },
    {
     "type": "Twitter",
     "id": "SupervisorJosie"
    }
   ]
  },
  {
   "name": "Alex Padilla",
   "address": [
    {
     "line1": "1500 11th Street,",
     "city": "Sacramento",
     "state": "CA",
     "zip": "95814"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(916) 653-7244"
   ],
   "emails": [
    "secretary.padilla@sos.ca.gov"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "CaliforniaSOS"
    },
    {
     "type": "Twitter",
     "id": "CASOSvote"
    }
   ]
  },
  {
   "name": "John Chiang",
   "address": [
    {
     "line1": "P.O. Box 942809",
     "city": "Sacramento",
     "state": "CA",
     "zip": "94209"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(916) 653-2995"
   ],
   "channels": [
    {
     "type": "Twitter",
     "id": "STONewsroom"
    }
   ]
  },
  {
   "name": "Xavier Becerra",
   "address": [
    {
     "line1": "Office of the Attorney General",
     "line2": "1300 \"I\" Street",
     "city": "Sacramento",
     "state": "CA",
     "zip": "95814"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(916) 445-9555"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "XavierBecerra"
    },
    {
     "type": "Twitter",
     "id": "AGBecerra"
    }
   ]
  },
  {
   "name": "Tom Torlakson",
   "address": [
    {
     "line1": "1430 N Street,",
     "city": "Sacramento",
     "state": "CA",
     "zip": "95814"
    }
   ],
   "party": "Nonpartisan",
   "phones": [
    "(916) 319-0800"
   ],
   "emails": [
    "superintendent@cde.ca.gov"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "CAEducation"
    },
    {
     "type": "Twitter",
     "id": "cadepted"
    }
   ]
  },
  {
   "name": "Betty T. Yee",
   "address": [
    {
     "line1": "P.O. Box 942850",
     "city": "Sacramento",
     "state": "CA",
     "zip": "94250"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(916) 445-2636"
   ],
   "channels": [
    {
     "type": "Facebook",
     "id": "137732083043662"
    },
    {
     "type": "Twitter",
     "id": "CAController"
    }
   ]
  },
  {
   "name": "Dave Jones",
   "address": [
    {
     "line1": "300 Capitol Mall,",
     "city": "Sacramento",
     "state": "CA",
     "zip": "95814"
    }
   ],
   "party": "Democratic",
   "phones": [
    "(916) 492-3500"
   ],
   "channels": [
    {
     "type": "GooglePlus",
     "id": "108233445289196913395"
    },
    {
     "type": "Facebook",
     "id": "insurancecagov"
    },
    {
     "type": "Twitter",
     "id": "CDINews"
    }
   ]
  }
 ]
}

解析函数:

  //fetch json data from Civic API
    private void getData(){
        final ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.show();

        StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                progressDialog.dismiss();
                try{
                    JSONObject jsonObject = new JSONObject(response);
                    //first loop through offices array. Retrieve officeName value
                    JSONArray officesArray = jsonObject.getJSONArray("offices");        //One array for offices
                    JSONArray officialsArray = jsonObject.getJSONArray("officials");    //one array for officials
                    for (int i = 0; i < officesArray.length(); i++) {
                        JSONObject jsonOffices = officesArray.getJSONObject(i);
                        JSONObject jsonOfficials = officialsArray.getJSONObject(i);
                        JSONObject jsonAddress = jsonOfficials.getJSONObject("address");
                        String line1 = jsonAddress.getJSONObject("address").getString("line1");
                        String city = jsonAddress.getJSONObject("address").getString("city");
                        String state = jsonAddress.getJSONObject("address").getString("state");
                        String zip = jsonAddress.getJSONObject("address").getString("zip");
                        if (jsonOfficials.has("photoUrl")) {
                            Reps reps1 = new Reps(jsonOffices.getString("name"),
                                    jsonOfficials.getString("name"),
                                    jsonOfficials.getString("party"),
                                    jsonOfficials.getString("photoUrl"),
                                    line1,
                                    city,
                                    state,
                                    zip
                            );

                            repList.add(reps1);
                        } else {
                            Reps reps2 = new Reps(jsonOffices.getString("name"),
                                    jsonOfficials.getString("name"),
                                    jsonOfficials.getString("party"),
                                    line1,
                                    city,
                                    state,
                                    zip
                           );

                            repList.add(reps2);
                        }
                    }
                    adapter = new RepRvAdapter(repList, getApplicationContext());
                    myrv.setAdapter(adapter);
                }catch (JSONException e){
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("Volley", error.toString());
                progressDialog.dismiss();
            }
        });
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
    }

logcat 错误说 JSONArray 无法转换为 JSONObject

我明白为什么会出现此错误。这是因为我在 JSON 数组上调用 .getJSONObject,但我不确定如何修复它。

编辑:添加了一些日志标签以进行故障排除。似乎没有找到 Denise Trager Dvorak 的地址值。这就是错误所在。我如何解决它?

【问题讨论】:

    标签: android arrays json


    【解决方案1】:

    正如您所说,address 是一个 JSONArray,其中包含一个带有地址信息的对象。

    所以你需要访问数组中的第一个对象并从那里获取信息,如下所示:

        //fetch json data from Civic API
    private void getData(){
        final ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.show();
    
        StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                progressDialog.dismiss();
                try{
                    JSONObject jsonObject = new JSONObject(response);
                    //first loop through offices array. Retrieve officeName value
                    JSONArray officesArray = jsonObject.getJSONArray("offices");        //One array for offices
                    JSONArray officialsArray = jsonObject.getJSONArray("officials");    //one array for officials
                    for (int i = 0; i < officesArray.length(); i++) {
                        JSONObject jsonOffices = officesArray.getJSONObject(i);
                        JSONObject jsonOfficials = officialsArray.getJSONObject(i);
                        JSONArray jsonAddress = jsonOfficials.getJSONArray("address");
                        String line1 = jsonAddress.getJSONObject(0).getString("line1");
                        String city = jsonAddress.getJSONObject(0).getString("city");
                        String state = jsonAddress.getJSONObject(0).getString("state");
                        String zip = jsonAddress.getJSONObject(0).getString("zip");
                        if (jsonOfficials.has("photoUrl")) {
                            Reps reps1 = new Reps(jsonOffices.getString("name"),
                                    jsonOfficials.getString("name"),
                                    jsonOfficials.getString("party"),
                                    jsonOfficials.getString("photoUrl"),
                                    line1,
                                    city,
                                    state,
                                    zip
                            );
    
                            repList.add(reps1);
                        } else {
                            Reps reps2 = new Reps(jsonOffices.getString("name"),
                                    jsonOfficials.getString("name"),
                                    jsonOfficials.getString("party"),
                                    line1,
                                    city,
                                    state,
                                    zip
                            );
    
                            repList.add(reps2);
                        }
                    }
                    adapter = new RepRvAdapter(repList, getApplicationContext());
                    myrv.setAdapter(adapter);
                }catch (JSONException e){
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("Volley", error.toString());
                progressDialog.dismiss();
            }
        });
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
    }
    

    EDIT1:

    我已经修改了代码,以便使用您提供的 json 在我的机器上进行本地尝试,并且一切正常。在这里你可以看到图片:

    您能否在我之前发布的解决方案中记录一些结果,并检查是否某些对象没有地址,或者我们是否缺少其他内容。

    【讨论】:

    • 我更新了代码,但 logcat 仍然返回错误:JSONException: No value for address at line 156
    • 让我尝试做一些调整,我会发布工作代码
    • 我很感激!卡在这个问题上一段时间了。它总是在这 2 个 logcat 错误之间
    • 我在我的代码中添加了一些日志。我得到相同的输出,但在最后一个地址“一楼”之后我得到了错误。生病更新图片
    • 好的。问题是候选人 Denise Trager Dvorak 没有任何可用的地址数据
    猜你喜欢
    • 2013-10-22
    • 2021-04-13
    • 2016-08-08
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    • 2015-03-19
    相关资源
    最近更新 更多