首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Gson 解析多層巢狀 JSON 完整指南:從資料類定義到遞歸反序列化

     編輯:程式設計綜合問答

目標 JSON 結構分析

{
  \"code\": 0,
  \"message\": \"\",
  \"data\": [
    {
      \"info\": {\"id\": 0, \"name\": \"lina\", \"age\": 10},
      \"subclass\": []
    },
    {
      \"info\": {\"id\": 1, \"name\": \"may\", \"age\": 16},
      \"subclass\": [
        {\"info\": {\"id\": 2, \"name\": \"aa\", \"age\": 13}, \"subclass\": []},
        {\"info\": {\"id\": 3, \"name\": \"bb\", \"age\": 12}, \"subclass\": []}
      ]
    }
  ]
}

特徵:data 為陣列,元素包含 info 物件與 subclass 同結構陣列 → **遞歸樹狀結構**。

資料類定義(Kotlin / Java)

// Java (Lombok @Data 簡寫)
@Data
class Response {
    int code;
    String message;
    List<Node> data;
}

@Data
class Node {
    Info info;
    List<Node> subclass;  // 遞歸引用自身
}

@Data
class Info {
    int id;
    String name;
    int age;
}

Gson 反序列化核心代碼

Gson gson = new GsonBuilder().create();
Response resp = gson.fromJson(jsonString, Response.class);

// 遞歸遍歷樹結構
void printTree(Node node, int depth) {
    String indent = \"  \".repeat(depth);
    System.out.println(indent + node.info.id + \" \" + node.info.name + \" \" + node.info.age);
    if (node.subclass != null) {
        for (Node child : node.subclass) printTree(child, depth + 1);
    }
}

for (Node root : resp.data) printTree(root, 0);

關鍵注意點

  1. 遞歸類型擦除:Gson 能正確處理 List<Node> subclass 因為泛型資訊在編譯期保留於簽名中(ParameterizedType),無需額外 TypeToken。
  2. 空陣列 vs null:JSON 中 \"subclass\": [] 會映射為空 ArrayList(非 null),遍歷時安全。
  3. 字段命名策略:若 JSON 為 snake_case(user_name),需設定 gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)。
  4. 日期/枚舉/自定義類型:註冊對應 TypeAdapter。

進階:流式解析大型 JSON(低記憶體)

JsonReader reader = new JsonReader(new StringReader(jsonString));
reader.beginObject();
while (reader.hasNext()) {
    String name = reader.nextName();
    if (\"data\".equals(name)) {
        reader.beginArray();
        while (reader.hasNext()) parseNode(reader); // 手寫遞歸解析邏輯
        reader.endArray();
    } else reader.skipValue();
}
reader.endObject();

適用於超大 JSON(>100MB),避免全量載入記憶體。

常見坑與排查

  • JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY → 資料類結構與 JSON 不匹配,檢查 List<Node> data vs 物件。
  • 遞歸深度過大導致 StackOverflowError → 改用迭代式遍歷或增加 JVM 棧大小 -Xss4m。
  • 循環引用(父引用子、子引用父) → Gson 預設不支援,需自定義 TypeAdapter 或使用 @Expose 控制序列化方向。

總結

定義遞歸資料類 Node { Info info; List<Node> subclass; },Gson 一行代碼完成全樹反序列化。配合遞歸遍歷即可提取任意層級資料。大型 JSON 可改用 JsonReader 流式解析。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved