You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android RecyclerView中解析非标准JSON对象流的问题咨询

问题解决方案

报错根因

你当前遇到的org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject报错和JSON拼接格式无关,是网络请求代码逻辑错误导致的:

  • 你直接使用urlConnection.getErrorStream()读取返回内容,该流仅在接口返回4xx/5xx错误状态码时才有值,你实际拿到的是错误页面的HTML内容,开头为<!DOCTYPE,自然无法转换为JSONObject。
  • 正常请求成功的返回内容需要从urlConnection.getInputStream()读取,需要先判断请求状态码再选择对应流。

拼接JSONObject的解析方案

多个直接拼接的JSONObject不需要强制要求后端修改为标准JSON格式,完全可以自行拆分解析,有两种常用实现方案:

方案1:大括号匹配拆分(兼容性最好)

通过统计大括号层数拆分单个完整JSON对象,不受JSON内部转义字符影响:

List<JSONObject> objectList = new ArrayList<>();
int bracketCount = 0;
StringBuilder currentJson = new StringBuilder();

for (char c : s.toCharArray()) {
    if (c == '{') bracketCount++;
    if (bracketCount > 0) currentJson.append(c);
    if (c == '}') {
        bracketCount--;
        if (bracketCount == 0) {
            // 已拿到完整的单个JSON对象
            objectList.add(new JSONObject(currentJson.toString()));
            currentJson.setLength(0); // 清空缓存准备解析下一个
        }
    }
}

拿到objectList后遍历每个对象执行你原有解析逻辑,将字段存入对应列表即可喂给RecyclerView Adapter。

方案2:转换为标准JSON数组(代码最简)

对返回字符串做简单格式化,直接转为JSONArray解析,注意要过滤掉末尾不完整的半截JSON:

s = s.trim();
// 过滤示例末尾不完整的单独{
if (s.endsWith("{")) {
    s = s.substring(0, s.length() - 1);
}
// 替换拼接符、首尾加数组括号,转为标准JSON数组格式
String arrayFormatStr = "[" + s.replace("}{", "},{") + "]";
JSONArray jsonArray = new JSONArray(arrayFormatStr);

// 遍历数组解析所有字段
for (int i = 0; i < jsonArray.length(); i++) {
    JSONObject obj = jsonArray.getJSONObject(i);
    // 原有解析逻辑
    JSONObject toNameObject = obj.getJSONObject("to");
    toNameList.add(toNameObject.getString("name"));
    JSONObject fromNameObject = obj.getJSONObject("from");
    fromNameList.add(fromNameObject.getString("name"));
    timeStampList.add(obj.getString("timestamp"));
}

原有请求代码修复点

修改网络请求部分的流读取逻辑:

int statusCode = urlConnection.getResponseCode();
InputStream in;
// 根据状态码选择正确的读取流
if (statusCode >= 200 && statusCode < 300) {
    in = urlConnection.getInputStream();
} else {
    in = urlConnection.getErrorStream();
}
InputStreamReader isw = new InputStreamReader(in);
// 后续流读取逻辑不变

补充说明:AsyncTask已在Android 11及以上版本废弃,长期迭代建议替换为OkHttp、Retrofit等成熟网络请求框架。

内容的提问来源于stack exchange,提问作者beastlyCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:39:01