java怎么遍历json

在 Java 中,可借助 Jackson、Gson 等库将 JSON 转为 Map 或 List,通过迭代器或 for 循环遍历其键值对来

在Java中遍历JSON数据是开发过程中常见的需求,尤其在与前后端交互、配置文件解析或数据处理场景中频繁出现,由于Java本身不提供内置的JSON解析器,开发者通常借助第三方库实现这一功能,以下从核心概念主流实现方式典型场景示例工具对比四个维度展开详解,并附完整代码演示和常见问题解答。

java怎么遍历json


基础认知:JSON的数据形态与遍历本质

JSON(JavaScript Object Notation)是一种轻量级数据交换格式,其核心由两种基本结构组成:
| 类型 | 特征 | 遍历目标 |
|————|———————————————————————-|——————————|
| 对象 | 键值对集合({"name":"张三", "age":25}),无序且允许重复键 | 遍历所有键及对应的值 |
| 数组 | 有序的值序列([1, "a", true]),通过索引访问元素 | 按顺序遍历每个元素 |

实际业务中常遇到混合结构(如对象包含数组,数组元素又是对象),此时需递归或分层遍历,理解这一特性是编写健壮遍历逻辑的关键。


主流实现方案详解

方案1:基于org.json库(轻量化首选)

这是Apache许可的纯Java实现,适合简单场景,核心类为JSONObject(表示对象)和JSONArray(表示数组)。

关键步骤:

  1. 构建JSON实例:可通过字符串构造或读取文件/网络流

    // 从字符串创建
    String jsonStr = "{"users":[{"id":1,"name":"李四"},{"id":2,"name":"王五"}]}";
    JSONObject jsonObj = new JSONObject(jsonStr);
    // 从文件读取(需处理IO异常)
    File file = new File("data.json");
    JSONObject fileJson = new JSONObject(new String(Files.readAllBytes(file.toPath())));
  2. 遍历逻辑

    • 遍历对象:通过keys()获取所有键,再用get()取值
      Set<String> keys = jsonObj.keySet(); // 获取所有键
      for (String key : keys) {
          Object value = jsonObj.get(key); // 值可能是基本类型/对象/数组
          System.out.println(key + " -> " + value);
      }
    • 遍历数组:通过length()get(index)逐项访问
      JSONArray userArray = jsonObj.getJSONArray("users");
      for (int i = 0; i < userArray.length(); i++) {
          JSONObject user = userArray.getJSONObject(i);
          System.out.println("用户ID:" + user.getInt("id") + ", 姓名:" + user.getString("name"));
      }
  3. 特殊处理

    • 判断字段是否存在:has(key)
    • 类型安全获取:getString(), getInt()等方法自动转换类型
    • 嵌套结构处理:若值为JSONObjectJSONArray,可继续调用对应方法深入遍历

优势:无需额外配置,API直观;缺点:复杂场景下代码冗余度高。

java怎么遍历json


方案2:Jackson库(企业级标准)

Jackson是目前最流行的JSON处理库之一,支持流式解析和注解驱动映射,适合高性能和复杂需求。

核心组件
| 类/接口 | 用途 | 典型用法 |
|——————|—————————————-|———————————–|
| ObjectMapper | 主入口,负责读写操作 | new ObjectMapper().readValue() |
| JsonNode | 抽象节点,可表示任意JSON结构 | traverse()方法实现深度遍历 |
| TypeReference | 解决泛型集合反序列化问题 | 配合readValue()使用 |

遍历实践

  1. 基础对象遍历

    ObjectMapper mapper = new ObjectMapper();
    JsonNode rootNode = mapper.readTree(jsonStr); // 转为树形结构
    // 遍历顶层字段
    Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
    while (fields.hasNext()) {
        Map.Entry<String, JsonNode> entry = fields.next();
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }
  2. 数组遍历

    JsonNode users = rootNode.get("users"); // 假设users是数组
    if (users.isArray()) {
        for (JsonNode user : users) { // Jackson自动迭代数组元素
            System.out.println("用户ID:" + user.get("id").asInt() + ", 姓名:" + user.get("name").asText());
        }
    }
  3. 高级特性

    • 流式处理:使用JsonParser逐事件读取,内存占用极低,适用于GB级大文件
      JsonParser parser = mapper.createParser(jsonStr);
      while (parser.nextToken() != null) {
          if (parser.currentToken() == FieldName) {
              parser.getText(); // 读取当前字段值
          }
      }
    • POJO映射:将JSON直接映射到Java对象,无需手动遍历
      public class User {
          private int id;
          private String name;
          // getter/setter省略
      }
      List<User> users = mapper.readValue(rootNode.get("users"), new TypeReference<List<User>>(){});

优势:功能强大,支持流式处理、注解配置、复杂类型映射;缺点:学习曲线较陡。


方案3:Gson库(简洁易用)

Google开发的Gson以简洁著称,特别适合快速开发。

java怎么遍历json

核心方法

  • fromJson():将JSON转为Java对象
  • toJson():将Java对象转为JSON
  • entrySet():遍历Map风格的JSON对象

遍历示例

Gson gson = new Gson();
JsonElement element = gson.fromJson(jsonStr, JsonElement.class); // 转为通用元素
if (element.isJsonObject()) {
    JsonObject obj = element.getAsJsonObject();
    for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }
} else if (element.isJsonArray()) {
    JsonArray arr = element.getAsJsonArray();
    for (JsonElement e : arr) {
        System.out.println(e.getAsString()); // 根据实际类型调用getAsXxx()
    }
}

特色功能

  • 空值处理:serializeNulls()控制是否序列化null值
  • 日期格式化:通过setDateFormat()自定义日期模式
  • 排除字段:使用@Expose注解精细控制序列化行为

方案对比表

维度 org.json Jackson Gson
依赖体积 较小 较大(含模块) 中等
学习成本
性能 一般 最优(尤其流式) 良好
功能丰富度 基础功能 全面(含流式) 实用级
社区支持 活跃 非常活跃 活跃
适用场景 小型项目 大型系统/大数据 快速开发

典型场景解决方案

场景1:未知结构的动态JSON处理

当接收到结构不固定的JSON时,应采用通用节点遍历:

// Jackson实现
JsonNode node = new ObjectMapper().readTree(jsonStr);
processNode(node); // 递归处理子节点
private void processNode(JsonNode node) {
    if (node.isObject()) {
        node.fields().forEachRemaining(entry -> {
            System.out.println("Key: " + entry.getKey());
            processNode(entry.getValue()); // 递归处理嵌套结构
        });
    } else if (node.isArray()) {
        node.forEach(this::processNode); // 递归处理数组元素
    } else {
        System.out.println("Value: " + node.asText());
    }
}

场景2:高性能大文件处理

对于超过100MB的JSON文件,必须使用流式解析:

// Jackson流式处理示例
JsonFactory factory = new JsonFactory();
try (InputStream in = new FileInputStream("large.json")) {
    JsonParser parser = factory.createParser(in);
    while (parser.nextToken() != null) {
        if (parser.currentToken() == FieldName) {
            String fieldName = parser.getCurrentName();
            parser.nextToken(); // 移动到值位置
            String value = parser.getText();
            // 处理字段...
        }
    }
} catch (IOException e) {
    e.printStackTrace();
}

常见问题FAQs

Q1: 如何处理JSON中的重复键?

A: 根据JSON规范,对象不允许重复键,若输入包含重复键,不同库的处理方式不同:

  • org.json:后出现的键会覆盖前者
  • Jackson/Gson:默认保留最后一个值,可通过DeserializationFeature.FAIL_ON_DUP_FIELD_NAME(Jackson)或自定义反序列化器调整行为,建议在生成JSON时避免重复键。

Q2: 遇到复杂嵌套结构如何高效遍历?

A: 推荐使用递归算法,结合具体库的特性:

  • Jackson:利用JsonNodeisObject()/isArray()判断类型,递归处理子节点
  • Gson:通过JsonElement的类型检查(isJsonObject()/isJsonArray())实现递归
  • 注意设置最大递归深度防止栈溢出,例如Jackson可通过DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES过滤无关字段。

归纳建议

需求场景 推荐方案 理由
小型项目/快速原型 Gson API简单,学习成本低
企业级应用/大数据 Jackson 性能优异,功能全面
教学/简单演示 org.json 无需复杂配置,直观易懂
需要严格类型校验 Jackson+POJO 编译期类型检查,减少运行时

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/100680.html

(0)
酷盾叔的头像酷盾叔
上一篇 2025年8月10日 17:37
下一篇 2025年6月6日 06:36

相关推荐

  • Java怎么正确做非空判断?避免空指针

    Java非空判断主要使用条件语句检查对象是否为null,基本写法:if (obj != null) {…},对于字符串需额外检查空串:if (str != null && !str.isEmpty()),Java 8+推荐用Optional类优雅处理空值。

    2025年6月21日
    300
  • java怎么调用main方法

    Java中,调用main方法通常是通过运行包含main方法的类,使用命令行工具时,

    2025年7月29日
    200
  • Java快速生成11位数的方法有哪些?

    在Java中生成11位随机数,可使用以下方法:,“java,long number = 10000000000L + (long)(Math.random() * 90000000000L);,`,或使用Random类:,`java,Random rand = new Random();,long number = rand.nextLong(10000000000L, 100000000000L);,“,确保结果在10000000000至99999999999之间,注意处理数值范围以避免溢出。

    2025年5月30日
    200
  • java中与或非怎么运算的

    Java中,与(&&)、或(||)和非(!)运算符用于布尔逻辑运算,与运算符(&&)当两个条件都为真时结果为真;或运算符(||)当至少一个条件为真时结果为真;

    2025年7月29日
    100
  • Java如何读取文档内容?

    在Java中读取文档内容可使用多种方式: ,1. **FileReader + BufferedReader**:逐行读取文本文件,适合大文件处理。 ,2. **Files.readAllLines()**:一次性读取所有行到List,适用于小文件。 ,3. **Files.readString()**(JDK11+):直接读取整个文件为字符串。 ,4. **Scanner类**:支持按分隔符解析内容。 ,需注意字符编码(如StandardCharsets.UTF_8)和异常处理(捕获IOException)。

    2025年7月6日
    100

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN