当前位置:首页 > 后端开发 > 正文

java 怎么遍历json

在 Java 中遍历 JSON 可借助第三方库(如 Jackson、Gson、org.json),先将 JSON 字符串解析为 JsonNode/ JsonObject(Jackson)或 JsonElement(Gson),再通过递归或迭代方式遍历键

前置准备:选择适合的JSON处理库

Java生态中有多个成熟的JSON处理库,最常用的三者及其特点如下表所示:

库名称 特点 适用场景
Jackson 高性能、功能全面(支持注解绑定/流式API)、广泛集成于Spring框架 企业级应用、复杂对象映射
Gson 轻量级、语法简洁、对泛型支持友好 快速开发、移动端应用
org.json 纯Java实现、无依赖、API简单直观 小型项目、教学演示

推荐优先学习Jackson(工业标准)和Gson(简洁高效),二者合计可覆盖90%以上的业务需求。


基于Jackson库的深度遍历方案

环境配置

Maven依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

核心实现步骤

步骤①:将JSON字符串转换为JsonNode对象
JsonNode是Jackson提供的树形结构节点,可灵活访问任意层级的数据。

步骤②:递归遍历节点类型
根据节点类型(对象/数组/值)进行差异化处理:

  • OBJECT → 遍历所有字段名+子节点
  • ARRAY → 遍历数组元素
  • VALUE → 获取具体值(字符串/数字/布尔值等)

完整代码示例

java 怎么遍历json  第1张

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
public class JacksonTraversal {
    private static void traverse(JsonNode node, String path) {
        if (node.isObject()) { // 处理JSON对象
            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> entry = fields.next();
                String newPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
                traverse(entry.getValue(), newPath);
            }
        } else if (node.isArray()) { // 处理JSON数组
            for (int i = 0; i < node.size(); i++) {
                String newPath = path + "[" + i + "]";
                traverse(node.get(i), newPath);
            }
        } else { // 基本类型值(终端节点)
            System.out.println("Path: " + path + " | Value: " + node.toString());
        }
    }
    public static void main(String[] args) throws IOException {
        String jsonStr = "{"name":"张三","age":30,"hobbies":["游泳","阅读"],"address":{"city":"北京","street":"长安街"}}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(jsonStr);
        traverse(rootNode, "");
    }
}

输出结果

Path: name | Value: "张三"
Path: age | Value: 30
Path: hobbies[0] | Value: "游泳"
Path: hobbies[1] | Value: "阅读"
Path: address.city | Value: "北京"
Path: address.street | Value: "长安街"

关键技巧

  • 路径拼接:通过path参数记录当前节点的访问路径,便于定位数据位置
  • 类型判断:必须严格区分isObject()isArray(),否则会抛出异常
  • 空值处理:可通过node.isNull()判断空节点,避免NPE

基于Gson库的扁平化遍历方案

环境配置

Maven依赖:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

核心实现思路

Gson默认将JSON转换为Map<String, Object>List<Object>,适合逐层展开的扁平化遍历。

代码示例

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.Stack;
public class GsonTraversal {
    public static void traverse(JsonElement element, String currentPath) {
        if (element.isJsonObject()) { // 处理JSON对象
            JsonObject obj = element.getAsJsonObject();
            for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
                String newPath = currentPath.isEmpty() ? entry.getKey() : currentPath + "." + entry.getKey();
                traverse(entry.getValue(), newPath);
            }
        } else if (element.isJsonArray()) { // 处理JSON数组
            JsonArray arr = element.getAsJsonArray();
            for (int i = 0; i < arr.size(); i++) {
                String newPath = currentPath + "[" + i + "]";
                traverse(arr.get(i), newPath);
            }
        } else { // 基本类型值
            System.out.println("Path: " + currentPath + " | Value: " + element.toString());
        }
    }
    public static void main(String[] args) {
        String jsonStr = "{"name":"李四","scores":[95,88,76],"info":{"gender":"男","height":175}}";
        Gson gson = new Gson();
        JsonElement root = JsonParser.parseString(jsonStr);
        traverse(root, "");
    }
}

输出结果

Path: name | Value: "李四"
Path: scores[0] | Value: 95
Path: scores[1] | Value: 88
Path: scores[2] | Value: 76
Path: info.gender | Value: "男"
Path: info.height | Value: 175

优势对比

  • Gson的API更简洁,无需显式创建ObjectMapper
  • 对原始类型(如整数、浮点数)的解析更直接
  • 适合需要快速验证数据结构的调试场景

特殊场景处理指南

动态键名的遍历(未知结构)

当JSON结构不固定时,需采用通用方式处理:

// Jackson实现
JsonNode dynamicNode = rootNode.get("dynamicKey");
if (dynamicNode != null && !dynamicNode.isMissingNode()) {
    // 继续遍历...
}
// Gson实现
if (root.has("dynamicKey")) {
    JsonElement ele = root.get("dynamicKey");
    // 处理逻辑...
}

大数据量的内存优化

对于超过1MB的JSON数据,建议改用流式API(仅Jackson支持):

ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getFactory().createParser(new File("large.json"));
while (parser.nextToken() != null) {
    // 按需处理每个token,避免全量加载到内存
}

复杂类型转换(如日期/枚举)

需配合自定义反序列化器:

// Jackson示例:注册模块处理日期格式
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module()); // Java8时间类支持
mapper.setDateFormat(df);

常见错误及解决方案

错误类型 原因分析 解决方法
JsonParseException JSON格式非规(如逗号缺失) 使用在线工具校验JSON格式
ClassCastException 尝试将数组强制转为对象 遍历前检查isArray()/isObject()
UnrecognizedPropertyException JSON包含未定义的字段 配置@JsonIgnoreProperties注解
OutOfMemoryError 单次加载过大JSON文件 改用流式解析或分割文件

相关问答FAQs

Q1: 如何从嵌套JSON中提取特定路径的值?

:以Jackson为例,可通过链式调用精确定位:

JsonNode cityNode = rootNode.path("address").path("city").get(); // 安全获取方式(不存在返回missing node)
String city = cityNode.asText(); // 转换为字符串

若使用Gson,需分段解析:

JsonObject addressObj = root.getAsJsonObject("address");
String city = addressObj.get("city").getAsString();

Q2: 遍历时遇到大量重复键怎么办?

:JSON规范允许对象内有重复键,但后续值会覆盖前者,若需保留所有值,应改用Multimap结构存储:

// Jackson解决方案
ObjectMapper mapper = new ObjectMapper();
List<JsonNode> values = mapper.readValue(jsonStr, new TypeReference<List<JsonNode>>(){});
// 后续按索引访问即可避免覆盖问题
0