
本文详解使用 org.json 库遍历多层嵌套 json(含数组内对象、对象内对象等)的通用方法,重点解决“无法访问 array 数组中元素”这一常见问题,并提供可直接运行的结构化代码示例。
在处理真实业务中的 JSON 数据时,嵌套结构极为常见:外层是 JSONArray(如 "Data" 字段),其每个元素是 JSONObject;而该对象内部又可能包含 JSONArray(如 "array")、嵌套 JSONObject(如 "anotherData"),甚至存在键名含数字或空格的非常规字段(如 "1foo"、"some more data")。若不明确区分每层数据类型并按需调用对应 getter 方法,极易抛出 JSONException: JSONObject["xxx"] is not a string. 或 JSONException: JSONObject["array"] is not a JSONArray. 等异常。
核心原则是:“先判断类型,再取值” —— 每次从 JSON 容器中提取子项前,必须根据字段语义和结构预期,选择 getJSONObject()、getJSONArray() 或 getString() 等精确方法,不可混用。
以下为完整、健壮的解析流程(基于 org.json:json 2023+ 版本):
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class NestedJsonParser {
public static List parseNestedJson(String rawJson) {
List dataList = new ArrayList<>();
JSONObject outer = new JSONObject(rawJson);
JSONArray dataArr = outer.getJSONArray("Data"); // ✅ 正确:从根对象取 "Data" 数组
for (int i = 0; i < dataArr.length(); i++) {
JSONObject jsonEvent = dataArr.getJSONObject(i); // ✅ 正确:取第 i 个事件对象
// 1️⃣ 解析顶层字段(字符串)
String foo = jsonEvent.optString("foo", ""); // 推荐用 optXxx() 避免空指针
String bar = jsonEvent.optString("bar", "");
// 2️⃣ 解析嵌套 JSONArray:"array"
JSONArray arrayJson = jsonEvent.getJSONArray("array"); // ✅ 必须用 getJSONArray()
String first1foo = "";
String second2foo = "";
if (arrayJson.length() > 0) {
JSONObject firstObj = arrayJson.getJSONObject(0); // ✅ 先取数组首元素(JSONObject)
first1foo = firstObj.optString("1foo", "");
}
if (arrayJson.length() > 1) {
JSONObject secondObj = arrayJson.getJSONObject(1);
second2foo = secondObj.optString("2foo", "");
}
// 3️⃣ 解析嵌套 JSONObject:"anotherData"
JSONObject anotherDataObj = jsonEvent.getJSONObject("anotherData"); // ✅ 必须用 getJSONObject()
String foofoo = anotherDataObj.optString("foofoo", "");
String barbar = anotherDataObj.optString("barbar", "");
// 4️⃣ 解析含空格键名(注意:JSON 标准允许,但需严格匹配)
String someMoreData = jsonEvent.optString("some more data", ""); // ✅ 键名含空格,必须原样书写
// 封装为业务对象(示例 Data 类需提前定义)
dataList.add(new Data(foo, bar, first1foo, second2foo, foofoo, barbar, someMoreData));
}
return dataList;
}
}? 关键注意事项:
- ❌ 错误示范:jsonEvent.getString("array") → "array" 是数组,不是字符串,会崩溃;
- ✅ 正确做法:jsonEvent.getJSONArray("array") → 明确声明期望类型;
- ? 键名 "1foo" 合法但易被误判为非法标识符——它只是普通字符串键,无需转义,直接 getString("1foo") 即可;
- ⚠️ "some more data" 含空格,必须原样传入键名字符串,不可写作 someMoreData;
- ? 强烈推荐使用 optString(key, defaultValue) 替代 getString(key),避免因字段缺失导致 JSONException;
- ? 若需深度遍历任意层级,可封装递归工具方法,但对固定结构,显式分层访问更清晰、高效、易调试。
通过严格遵循“类型驱动访问”原则,并结合 optXxx() 安全方法,即可稳定、准确地解析任意深度的嵌套 JSON,彻底告别 “Cannot cast to...” 异常。










