首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Gson 解析 JSON 完整實戰:從 JSONObject 到 JSONArray 深度解析

     編輯:Java 相關知識

前言:為什麼選擇 Gson?

Google Gson 是 Java 領域最流行的 JSON 庫之一,以 API 簡潔、效能優異、支援泛型、無需註解即可序列化/反序列化著稱。本文以真實天氣 API 回應為例,示範 Gson 解析巢狀物件、陣列、動態欄位的完整技巧。

範例 JSON 資料結構分析

{
  "resultcode": "200",
  "reason": "successed!",
  "result": {
    "sk": { "temp": "24", "wind_direction": "西南風", ... },
    "today": { 
      "temperature": "16℃~27℃", 
      "weather": "陰轉多雲",
      "weather_id": { "fa": "02", "fb": "01" },
      ...
    },
    "future": [
      { "date": "20150604", "weather": "陰轉多雲", ... },
      { "date": "20150605", "weather": "多雲轉晴", ... },
      ...
    ]
  },
  "error_code": 0
}

核心 API 快速查閱

類別用途關鍵方法
JsonParser解析 JSON 字串/串流 → JsonElementparse(String), parse(Reader)
JsonObject代表 JSON 物件 {}get(key), getAsString(), getAsJsonObject()
JsonArray代表 JSON 陣列 []size(), get(index), iterator()
JsonPrimitive代表基本值 (字串/數字/布林)getAsString(), getAsInt(), getAsBoolean()

實作一:解析巢狀 JSONObject

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.FileReader;

public class ParseJsonObject {
    public static void main(String[] args) {
        JsonParser parser = new JsonParser();
        
        try (FileReader reader = new FileReader("weather.json")) {
            // 1. 解析根節點
            JsonObject root = parser.parse(reader).getAsJsonObject();
            
            // 2. 取得基本欄位
            System.out.println("resultcode: " + root.get("resultcode").getAsString());
            System.out.println("reason: " + root.get("reason").getAsString());
            
            // 3. 深層巢狀導航
            JsonObject result = root.get("result").getAsJsonObject();
            JsonObject today = result.get("today").getAsJsonObject();
            
            System.out.println("week: " + today.get("week").getAsString());
            System.out.println("weather: " + today.get("weather").getAsString());
            System.out.println("city: " + today.get("city").getAsString());
            
            // 4. 進一步巢狀:weather_id 物件
            JsonObject weatherId = today.get("weather_id").getAsJsonObject();
            System.out.println("fa: " + weatherId.get("fa").getAsString());
            System.out.println("fb: " + weatherId.get("fb").getAsString());
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

實作二:解析 JSONArray 陣列遍歷

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.FileReader;

public class ParseJsonArray {
    public static void main(String[] args) {
        JsonParser parser = new JsonParser();
        
        try (FileReader reader = new FileReader("weather.json")) {
            JsonObject root = parser.parse(reader).getAsJsonObject();
            JsonObject result = root.get("result").getAsJsonObject();
            
            // 1. 取得 future 陣列
            JsonArray futureArray = result.get("future").getAsJsonArray();
            System.out.println("未來 " + futureArray.size() + " 天預報:");
            
            // 2. 遍歷陣列
            for (int i = 0; i < futureArray.size(); i++) {
                JsonObject day = futureArray.get(i).getAsJsonObject();
                System.out.println("------ 第 " + (i+1) + " 天 ------");
                System.out.println("date: " + day.get("date").getAsString());
                System.out.println("week: " + day.get("week").getAsString());
                System.out.println("weather: " + day.get("weather").getAsString());
                System.out.println("temperature: " + day.get("temperature").getAsString());
                System.out.println("wind: " + day.get("wind").getAsString());
            }
            
            // 3. 使用 Iterator 更優雅
            System.out.println("\n--- Iterator 遍歷 ---");
            for (JsonElement element : futureArray) {
                JsonObject day = element.getAsJsonObject();
                System.out.println(day.get("week") + " : " + day.get("weather"));
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

進階技巧:安全取值與預設值處理

/** 安全取得字串值,避免 NullPointerException */
private static String safeGetString(JsonObject obj, String key, String defaultValue) {
    return obj.has(key) && !obj.get(key).isJsonNull() 
        ? obj.get(key).getAsString() 
        : defaultValue;
}

/** 安全取得整數值 */
private static int safeGetInt(JsonObject obj, String key, int defaultValue) {
    return obj.has(key) && !obj.get(key).isJsonNull() 
        ? obj.get(key).getAsInt() 
        : defaultValue;
}

/** 使用範例 */
String city = safeGetString(today, "city", "未知城市");
int temp = safeGetInt(today, "temp", -999);

檔案路徑注意事項

相對路徑基準:專案根目錄 (即 pom.xml 所在層級),而非 src 目錄。
建議使用 new FileReader("src/main/resources/weather.json") 或 getClass().getResourceAsStream("/weather.json") (資源檔案置於 resources 目錄)

執行結果截圖

Gson 進階功能預覽

  • 直接映射到 POJO:gson.fromJson(json, WeatherResponse.class) - 最推薦的生產環境用法
  • 自定義 TypeAdapter:處理特殊日期格式、Enum 序列化
  • @SerializedName 註解:JSON 欄位與 Java 屬性名不一致時映射
  • 流式處理大型 JSON:JsonReader/JsonWriter 低記憶體佔用

常見錯誤與除錯技巧

錯誤原因解決
IllegalStateException: Not a JSON Object對 JsonArray 呼叫 getAsJsonObject()先用 isJsonObject() 檢查類型
NullPointerException欄位不存在或為 null使用 has(key) 與 isJsonNull() 雙重檢查
NumberFormatException數值欄位實為字串 (如 "24")統一用 getAsString() 再轉型,或定義 POJO 時用 String 接收

Gson 的樹模型 API (JsonParser/JsonObject/JsonArray) 適合處理結構不固定、無法預先定義 POJO 的動態 JSON 場景。掌握其導航與安全取值技巧,能靈活應對各種複雜 JSON 解析需求。

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