Google Gson 是 Java 領域最流行的 JSON 庫之一,以 API 簡潔、效能優異、支援泛型、無需註解即可序列化/反序列化著稱。本文以真實天氣 API 回應為例,示範 Gson 解析巢狀物件、陣列、動態欄位的完整技巧。
{
"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
}
| 類別 | 用途 | 關鍵方法 |
|---|---|---|
JsonParser | 解析 JSON 字串/串流 → JsonElement | parse(String), parse(Reader) |
JsonObject | 代表 JSON 物件 {} | get(key), getAsString(), getAsJsonObject() |
JsonArray | 代表 JSON 陣列 [] | size(), get(index), iterator() |
JsonPrimitive | 代表基本值 (字串/數字/布林) | getAsString(), getAsInt(), getAsBoolean() |
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();
}
}
}
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.fromJson(json, WeatherResponse.class) - 最推薦的生產環境用法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 解析需求。