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

如何读取JSON文件中API返回数组内enrollments下的user_id?

解决Gson读取JSON数组提取user_id的问题

问题场景

已通过FileWriter和com.google.gson包将API返回数据保存到Courses.json文件,需要提取enrollments下的user_id数据,但编写的读取代码报错。

精简后的Courses.json内容

[
  {
    "access_restricted_by_date":true,
    "id":3155
  },
  {
    "access_restricted_by_date":true,
    "id":4604
  },
  {
    "access_restricted_by_date":true,
    "id":4655
  },
  {
    "root_account_id":1,
    "storage_quota_mb":50000,
    "template":false,
    "end_at":null,
    "public_syllabus_to_auth":false,
    "public_syllabus":false,
    "created_at":"2022-08-11T18:00:41Z",
    "start_at":null,
    "enrollment_term_id":180,
    "uuid":"MC24SbWdGDjeKTalLT5T5V41Foh0jD4EybOFG8xY",
    "course_code":"Study Hall",
    "course_color":null,
    "grading_standard_id":null,
    "workflow_state":"available",
    "id":6312,
    "homeroom_course":false,
    "default_view":"assignments",
    "is_public_to_auth_users":false,
    "grade_passback_setting":null,
    "enrollments":[
      {
        "role":"StudentEnrollment",
        "enrollment_state":"active",
        "role_id":3,
        "user_id":9999,
        "type":"student",
        "limit_privileges_to_course_section":false
      }
    ],
    "blueprint":false,
    "license":"private",
    "is_public":false
    }
]

错误代码及报错信息

尝试读取id的代码:

import java.io.*;
import com.google.gson.*;
import com.google.gson.stream.*;
import java.io.IOException;
public class CourseGradeReader {
    public static void main(String args[]) {
        JsonReader reader;
        try {
            reader = new JsonReader(new FileReader("Courses.json"));
            reader.beginArray();
            while(reader.hasNext()) {
                String name = reader.nextName();
                if(name.equals("id")) {
                    System.out.println(reader.nextString());
                    reader.endArray();
                } else {
                    reader.skipValue();
                }
            }
            reader.endObject();
            reader.close();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

运行后报错:

java.lang.IllegalStateException: 预期是名称但实际是BEGIN_OBJECT,位于第1行第3列路径$[0]
	at com.google.gson.stream.JsonReader.nextName(JsonReader.java:790)
	at org.example.CourseGradeReader.main(CourseGradeReader.java:12)

错误原因

代码逻辑错误:JSON最外层是数组,数组内的每个元素是对象,调用reader.beginArray()后,当前指针指向数组的第一个对象起始位置(BEGIN_OBJECT),此时直接调用nextName()会报错,因为nextName()只能在对象的键名位置调用。另外,id是数字类型,用nextString()也会导致类型不匹配。

解决方案

方案1:修正流式JsonReader代码

按照JSON的层级结构,嵌套处理数组和对象:

import java.io.FileReader;
import com.google.gson.stream.JsonReader;

public class CourseGradeReader {
    public static void main(String args[]) {
        try (JsonReader reader = new JsonReader(new FileReader("Courses.json"))) {
            reader.beginArray();
            while (reader.hasNext()) {
                reader.beginObject(); // 开始处理数组中的单个课程对象
                while (reader.hasNext()) {
                    String name = reader.nextName();
                    if (name.equals("id")) {
                        // id是数字类型,使用nextLong()/nextInt()读取
                        System.out.println("课程ID: " + reader.nextLong());
                    } else if (name.equals("enrollments")) {
                        // 处理enrollments数组
                        reader.beginArray();
                        while (reader.hasNext()) {
                            reader.beginObject();
                            while (reader.hasNext()) {
                                String enrollName = reader.nextName();
                                if (enrollName.equals("user_id")) {
                                    System.out.println("用户ID: " + reader.nextLong());
                                } else {
                                    reader.skipValue(); // 跳过不需要的字段
                                }
                            }
                            reader.endObject();
                        }
                        reader.endArray();
                    } else {
                        reader.skipValue(); // 跳过课程对象中其他不需要的字段
                    }
                }
                reader.endObject();
            }
            reader.endArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方案2:使用Gson对象映射(更简洁)

定义与JSON结构对应的实体类,让Gson自动完成映射,代码可读性更高:

import java.io.FileReader;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;

// 课程实体类,仅定义需要的字段
class Course {
    private long id;
    @SerializedName("enrollments")
    private List<Enrollment> enrollments;

    public long getId() {
        return id;
    }

    public List<Enrollment> getEnrollments() {
        return enrollments;
    }
}

// 选课实体类
class Enrollment {
    @SerializedName("user_id")
    private long userId;

    public long getUserId() {
        return userId;
    }
}

public class CourseGradeReader {
    public static void main(String args[]) {
        try (FileReader reader = new FileReader("Courses.json")) {
            Gson gson = new Gson();
            // 将JSON数组直接转换为Course对象数组
            Course[] courses = gson.fromJson(reader, Course[].class);
            
            for (Course course : courses) {
                System.out.println("课程ID: " + course.getId());
                if (course.getEnrollments() != null) {
                    for (Enrollment enrollment : course.getEnrollments()) {
                        System.out.println("用户ID: " + enrollment.getUserId());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

说明

  • 方案1适合处理超大JSON文件,内存占用低;
  • 方案2代码简洁,维护成本低,适合大多数场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 11:31:02