Gson 是 Google 開源的 Java JSON 庫,以「無需註解、支援泛型、處理不可修改類」三大特性著稱。本文從核心 API、泛型處理、自定義序列化、性能優化、常見坑點五個維度,系統講解 Gson 實戰精髓。
Gson gson = new Gson(); // 線程安全,可全局復用
// 1. 對象 -> JSON 字符串
User user = new User(1L, "張三", 25);
String json = gson.toJson(user);
// {"id":1,"name":"張三","age":25}
// 2. JSON 字符串 -> 對象
String jsonStr = "{\"id\":2,\"name\":\"李四\",\"age\":30}";
User user2 = gson.fromJson(jsonStr, User.class);
// 3. 支援 Reader/Writer 流式處理 (大數據/網絡流)
try (Reader reader = new FileReader("user.json");
Writer writer = new FileWriter("user_out.json")) {
User u = gson.fromJson(reader, User.class);
gson.toJson(u, writer);
}
Java 泛型運行期擦除,Gson 提供 TypeToken 捕獲完整類型信息:
// List
Type userListType = new TypeToken>() {}.getType();
List users = gson.fromJson(jsonArrayStr, userListType);
// Map
Type userMapType = new TypeToken
原理:匿名內部類繼承
TypeToken,通過getGenericSuperclass()獲取ParameterizedType,保留泛型參數。
// LocalDate 適配器 (Gson 默認不支援 java.time)
public class LocalDateAdapter implements JsonSerializer, JsonDeserializer {
private static final DateTimeFormatter FMT = DateTimeFormatter.ISO_LOCAL_DATE;
@Override public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.format(FMT));
}
@Override public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return LocalDate.parse(json.getAsString(), FMT);
}
}
// 註冊
Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
.create();
public class UserTypeAdapter extends TypeAdapter {
@Override public void write(JsonWriter out, User value) throws IOException {
out.beginObject();
out.name("id").value(value.getId());
out.name("name").value(value.getName());
out.name("age").value(value.getAge());
out.endObject();
}
@Override public User read(JsonReader in) throws IOException {
Long id = null; String name = null; Integer age = null;
in.beginObject();
while (in.hasNext()) {
switch (in.nextName()) {
case "id": id = in.nextLong(); break;
case "name": name = in.nextString(); break;
case "age": age = in.nextInt(); break;
default: in.skipValue();
}
}
in.endObject();
return new User(id, name, age);
}
}
// 註冊 (nullSafe 可選)
Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserTypeAdapter().nullSafe())
.create();
Gson gson = new GsonBuilder()
// 格式化輸出 (調試用)
.setPrettyPrinting()
// null 字段輸出 (默認忽略)
.serializeNulls()
// 日期格式化 (適用 Date/Calendar,java.time 需適配器)
.setDateFormat("yyyy-MM-dd HH:mm:ss")
// 字段命名策略 (駝峰 -> 下劃線)
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
// 排除字段 (多種方式)
.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(Transient.class) != null; // @Transient 忽略
}
@Override public boolean shouldSkipClass(Class> clazz) { return false; }
})
// 版本控制
.setVersion(1.0)
// 禁用 HTML 轉義 (默認轉義 < > & 等)
.disableHtmlEscaping()
// 允許單引號、註釋等非標準 JSON (寬鬆模式)
.setLenient()
.create();
| 場景/坑點 | 問題現象 | 解決方案 |
|---|---|---|
| java.time 類型 (LocalDate 等) | 序列化為對象而非字符串 | 註冊 TypeAdapter / 使用 gson-javatime-adapters |
| 循環引用 (A->B->A) | StackOverflowError | @Expose 只序列化單向 / 自定義 TypeAdapter 打破循環 / 使用 @Since 版本控制 |
| 字段名不一致 (camelCase vs snake_case) | 反序列化字段為 null | @SerializedName("user_name") 或 setFieldNamingPolicy |
| 數值精度丟失 (Long -> JS Number) | JS 端 Long 變不精確 | Long 序列化為 String: new TypeAdapter |
| 大 JSON 內存溢出 | OOM | 流式處理: gson.fromJson(reader, Type) / JsonReader 手動解析 |
| Map 鍵非 String | 鍵變為對象字符串 | enableComplexMapKeySerialization() (輸出 {"keyObj":val}) |
| 忽略未知字段 (兼容性) | 默認忽略,安全 | 無需配置,Gson 默認寬容未知字段 |
| 單例 Gson 實例 | 重複創建浪費資源 | 全局單例或 DI 容器管理,Gson 線程安全 |
Gson 線程安全,創建開銷大 (反射掃描),應用全局單例。JsonElement 對象創建,序列化/反序列化快 2-5 倍。JsonReader/JsonWriter 逐 token 處理,常駐內存極低。disableHtmlEscaping() 微幅提升性能 (前提是確信輸出不含 XSS 風險)。| 維度 | Gson | Jackson | Fastjson |
|---|---|---|---|
| 易用性 | ⭐⭐⭐⭐⭐ 簡潔 | ⭐⭐⭐ 功能豐富但複雜 | ⭐⭐⭐⭐ API 簡單 |
| 性能 | 優秀 | 極致 (後端首選) | 極致 (曾有安全漏洞) |
| 泛型支援 | 原生 TypeToken | TypeReference | TypeReference |
| java.time 支援 | 需適配器 | 內建模塊 | 內建支援 |
| 流式 API | TypeAdapter/JsonReader | JsonParser/JsonGenerator | JSONReader/JSONWriter |
| Spring Boot 默認 | 可切換 | 默認 | 不建議 |
| 推薦場景 | Android、中小項目、簡單需求 | 企業級後端、高性能、複雜序列化 | 舊項目維護、特定場景 |
toJson(obj) / fromJson(json, Type) 覆蓋 90% 場景。new TypeToken<List<User>>(){}.getType() 破除類型擦除。TypeAdapter (高性能流式) > JsonSerializer/Deserializer (簡便樹模型)。GsonBuilder 鏈式配置格式化、命名策略、null處理、版本、適配器註冊。Gson 以「簡單、直觀、無侵入」贏得廣大開發者青睞。掌握 TypeToken 與 TypeAdapter 兩大殺手鐧,即可應對 99% 的 JSON 處理場景。對於高性能、複雜序列化需求的企業級後端,Jackson 仍是首選;但對於 Android、中小型項目、快速原型開發,Gson 是性價比最高的選擇。