Gson 是 Google 開源的 Java JSON 庫,以 API 簡潔、效能優異、支援泛型與自定義類型適配聞名。本文提供 Maven/Gradle 依賴、核心 API、工具類封裝與常見坑點。
// Gradle
implementation 'com.google.code.gson:gson:2.10.1'
// Maven
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
Gson gson = new Gson();
// 物件 -> JSON
User user = new User("Alice", 25);
String json = gson.toJson(user); // {"name":"Alice","age":25}
// JSON -> 物件
User parsed = gson.fromJson(json, User.class);
// List -> JSON
List<User> users = Arrays.asList(new User("A",1), new User("B",2));
String listJson = gson.toJson(users);
// JSON -> List (需 TypeToken)
Type listType = new TypeToken<List<User>>(){}.getType();
List<User> parsedList = gson.fromJson(listJson, listType);
Gson gson = new GsonBuilder()
.setPrettyPrinting() // 格式化輸出
.disableHtmlEscaping() // 不轉義 HTML 字元
.serializeNulls() // 序列化 null 欄位
.setDateFormat("yyyy-MM-dd HH:mm:ss") // 統一日期格式
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter()) // 自定義適配器
.create();
public class GsonUtils {
private static final Gson GSON = new GsonBuilder()
.disableHtmlEscaping()
.registerTypeAdapter(Date.class, new DateSerializer())
.registerTypeAdapter(Date.class, new DateDeserializer())
.create();
public static <T> T fromJson(String json, Class<T> clazz) {
return GSON.fromJson(json, clazz);
}
public static <T> List<T> fromJsonList(String json, Class<T> clazz) {
Type type = TypeToken.getParameterized(List.class, clazz).getType();
return GSON.fromJson(json, type);
}
public static List<Map<String, Object>> fromJsonToListMap(String json) {
return GSON.fromJson(json, new TypeToken<List<Map<String, Object>>>(){}.getType());
}
public static String toJson(Object obj) {
return GSON.toJson(obj);
}
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 泛型擦除導致 List<T> 反序列化失敗 | 運行期無法獲取 T 的實際類型 | 使用 TypeToken 或 TypeToken.getParameterized() |
| 日期格式不一致 | 預設用 Date 默認 toString | setDateFormat() 或註冊 JsonSerializer/Deserializer |
| 循環引用 StackOverflowError | 雙向關聯無限遞迴 | 使用 @Expose 控制序列化欄位、或自定義適配器忽略反向引用 |
| 欄位命名不一致 (camelCase vs snake_case) | JSON 鍵與 Java 欄位名不同 | @SerializedName("user_name") 或設定 FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES |
| 大數字精度丟失 | JSON 數字映射為 double | 使用 BigDecimal 欄位、或註冊 NumberDeserializer |
Gson 實例 (線程安全)JsonReader/JsonWriter (SAX 風格)TypeToken 匿名類,提取為常量