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

Android中读取JSON Array时出现错误的技术咨询

解决Android中JSON Array解析错误的方案

嘿,我帮你梳理下这个JSON解析的问题!先看你提供的JSON结构,里面的options字段是个“变色龙”——有的是数组,有的是对象,这大概率是你解析时出错的核心原因。下面一步步给你讲怎么在Android里正确处理它:

先明确JSON的核心结构

你的JSON最外层是一个对象,包含名为data的数组,数组里的每个元素又嵌套了一个data对象,重点是这个嵌套data里的options:

  • 第一个元素的options是JSON数组(包含多个display项)
  • 第二个元素的options是JSON对象(包含left和right两个子对象)

如果解析时没区分这两种类型,直接强制转成数组或对象,肯定会抛类型转换异常!

方案1:用原生JSONObject/JSONArray解析(无第三方库)

这种方式适合不想引入第三方库的场景,关键是先判断options的类型再处理:

// 假设你的JSON字符串存在jsonStr变量中
try {
    JSONObject rootObj = new JSONObject(jsonStr);
    JSONArray dataArray = rootObj.getJSONArray("data");

    // 遍历外层data数组
    for (int i = 0; i < dataArray.length(); i++) {
        JSONObject itemObj = dataArray.getJSONObject(i);
        // 提取外层字段
        String id = itemObj.getString("id");
        int type = itemObj.getInt("type");
        int order = itemObj.getInt("order");

        // 提取嵌套的data对象
        JSONObject innerData = itemObj.getJSONObject("data");
        int innerType = innerData.getInt("type");
        int innerOrder = innerData.getInt("order");
        // 用optBoolean处理可选字段,避免字段不存在时崩溃
        boolean required = innerData.optBoolean("required", false);

        // 重点:判断options的类型
        Object optionsObj = innerData.get("options");
        if (optionsObj instanceof JSONArray) {
            // 处理数组类型的options(比如第一个元素的星级选项)
            JSONArray optionsArray = (JSONArray) optionsObj;
            for (int j = 0; j < optionsArray.length(); j++) {
                JSONObject optionItem = optionsArray.getJSONObject(j);
                String displayText = optionItem.getString("display");
                // 这里可以把displayText存入列表或做其他处理
            }
        } else if (optionsObj instanceof JSONObject) {
            // 处理对象类型的options(比如第二个元素的左右选项)
            JSONObject optionsObject = (JSONObject) optionsObj;
            JSONObject leftOpt = optionsObject.getJSONObject("left");
            String leftGoto = leftOpt.getString("goto");
            int leftDisplay = leftOpt.getInt("display");

            JSONObject rightOpt = optionsObject.getJSONObject("right");
            String rightGoto = rightOpt.getString("goto");
            // 注意你给的JSON里right的display字段截断了,根据实际数据处理即可
        }
    }
} catch (JSONException e) {
    e.printStackTrace();
    // 这里可以添加错误处理逻辑,比如提示解析失败
}

方案2:用Gson解析(更简洁,推荐)

如果项目里已经用了Gson,那定义实体类时要注意处理多类型的options和Java关键字goto:

第一步:定义实体类

import com.google.gson.annotations.SerializedName;
import java.util.List;

public class SurveyResponse {
    private List<SurveyItem> data;

    // Getter & Setter
    public List<SurveyItem> getData() { return data; }
    public void setData(List<SurveyItem> data) { this.data = data; }

    public static class SurveyItem {
        private String id;
        private int type;
        private int order;
        private SurveyInnerData data;

        // Getter & Setter
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public int getType() { return type; }
        public void setType(int type) { this.type = type; }
        public int getOrder() { return order; }
        public void setOrder(int order) { this.order = order; }
        public SurveyInnerData getData() { return data; }
        public void setData(SurveyInnerData data) { this.data = data; }

        public static class SurveyInnerData {
            // 注意:goto是Java关键字,必须用@SerializedName映射字段名
            @SerializedName("goto")
            private String gotoTarget;
            private int type;
            private int order;
            // 用Object接收多类型的options,后续再判断类型
            private Object options;
            private boolean required;
            private List<Object> answer;

            // Getter & Setter
            public String getGotoTarget() { return gotoTarget; }
            public void setGotoTarget(String gotoTarget) { this.gotoTarget = gotoTarget; }
            public int getType() { return type; }
            public void setType(int type) { this.type = type; }
            public int getOrder() { return order; }
            public void setOrder(int order) { this.order = order; }
            public Object getOptions() { return options; }
            public void setOptions(Object options) { this.options = options; }
            public boolean isRequired() { return required; }
            public void setRequired(boolean required) { this.required = required; }
            public List<Object> getAnswer() { return answer; }
            public void setAnswer(List<Object> answer) { this.answer = answer; }
        }
    }
}

第二步:解析JSON字符串

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

// 解析代码
Gson gson = new Gson();
SurveyResponse response = gson.fromJson(jsonStr, SurveyResponse.class);

// 遍历处理每个SurveyItem
for (SurveyResponse.SurveyItem item : response.getData()) {
    Object options = item.getData().getOptions();
    if (options instanceof JsonArray) {
        // 处理数组类型的options
        JsonArray optionsArray = (JsonArray) options;
        // 遍历数组提取display内容...
    } else if (options instanceof JsonObject) {
        // 处理对象类型的options
        JsonObject optionsObj = (JsonObject) options;
        JsonObject leftOpt = optionsObj.getAsJsonObject("left");
        // 提取left的字段...
    }
}

常见错误避坑指南

  • 类型转换异常:一定要先判断options是数组还是对象,不要直接调用getJSONArray或getJSONObject
  • 关键字冲突:goto是Java关键字,不能直接用作字段名,必须用@SerializedName映射
  • 可选字段崩溃:对于可能不存在的字段(比如required),用optXXX方法(原生)或者让实体类字段为Boolean(Gson),避免字段缺失时抛异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:41:36