Android中JsonReader解析Neo4j REST API Cypher查询JSON结果报错排查
嘿,这个问题我遇到过类似的情况,咱们一步步来解决它!
首先得明确Neo4j REST API返回的JSON结构——根节点是一个对象,不是数组也不是字符串,里面包含columns(一维数组)和data(二维数组)两个字段。你之前的错误就是没按这个结构来解析,直接去读字符串或者错误地开启数组解析,才会抛出Expected a string but was BEGIN_ARRAY异常。
下面给你两种可行的解析方案,都基于你用的Google Simple JSON库:
方案一:用JsonReader流式解析(适合大体积JSON)
这种方式逐字符读取,内存占用低,适合返回数据量较大的场景,关键是要严格匹配JSON的层级结构:
// 先获取HTTP响应的实体 HttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); // 创建JsonReader并开始解析根对象 JsonReader reader = new JsonReader(new InputStreamReader(entity.getContent())); reader.beginObject(); // 根是对象,必须先调用这个 while (reader.hasNext()) { String fieldName = reader.nextName(); switch (fieldName) { case "columns": // 处理columns一维数组 reader.beginArray(); while (reader.hasNext()) { String column = reader.nextString(); // 这里可以把列名存入集合,比如List<String> columnsList.add(column); } reader.endArray(); break; case "data": // 处理data二维数组(每个元素又是一个数组) reader.beginArray(); while (reader.hasNext()) { reader.beginArray(); // 开启每一行的数组 while (reader.hasNext()) { String value = reader.nextString(); // 处理单个数据值,比如"1607174" } reader.endArray(); // 结束当前行的数组 } reader.endArray(); break; default: reader.skipValue(); // 跳过其他未知字段,避免解析出错 break; } } reader.endObject(); // 结束根对象解析 reader.close();
方案二:用JSONObject一次性解析(更直观)
如果返回的JSON数据量不大,直接把响应转成字符串后用JSONObject解析会更简单,不容易出错:
// 把HTTP响应实体转成字符串 HttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); String jsonStr = EntityUtils.toString(entity); // 解析成JSONObject JSONObject rootObj = new JSONObject(jsonStr); // 获取columns数组 JSONArray columnsArr = rootObj.getJSONArray("columns"); for (int i = 0; i < columnsArr.length(); i++) { String columnName = columnsArr.getString(i); // 处理列名 } // 获取data二维数组 JSONArray dataArr = rootObj.getJSONArray("data"); for (int i = 0; i < dataArr.length(); i++) { JSONArray rowArr = dataArr.getJSONArray(i); for (int j = 0; j < rowArr.length(); j++) { String dataValue = rowArr.getString(j); // 处理每个数据值,比如你的"1607174" } }
关键注意点
- 必须先解析根对象:Neo4j返回的是
{...},所以第一步要调用beginObject()(流式解析)或者直接用JSONObject包裹(一次性解析),不能直接去读字符串或开启数组。 - 层级要对应:每个
beginArray()必须有对应的endArray(),每个beginObject()必须有对应的endObject(),否则会抛出解析异常。 - 跳过未知字段:如果API返回了额外字段,一定要用
skipValue()跳过,避免解析中断。
内容的提问来源于stack exchange,提问作者Thomas Morgan
相关产品推荐
相关产品推荐

