本文提供一個涵蓋 單一 Bean、List 集合、陣列、Map、巢狀對象、日期、Boolean、StringBuffer 等多種數據結構的完整 Gson 序列化/反序列化測試類。所有代碼可直接複製到 IDE 運行 (需引入 Gson Jar),輸出結果已驗證,適合作為專案快速參考與學習範本。
public class User { private String name; private int age; private StringBuffer sex; // 故意用 StringBuffer 測試非標準類型 private boolean isChild; public User(String name, int age, StringBuffer sex, boolean isChild) { this.name = name; this.age = age; this.sex = sex; this.isChild = isChild; } // getter/setter/toString/hashCode 省略 // toString 格式:{name=...;age=...;sex=...;isChild=...} } import com.google.gson.*; import com.google.gson.reflect.TypeToken; import java.util.*; public class GsonTest { public static void main(String[] args) { Gson gson = new Gson(); // ==================== 1. 單一 Bean ==================== System.out.println("=== 1. Bean ==="); User u1 = new User("鳳姐", 12, new StringBuffer("未知"), true); String json = gson.toJson(u1); System.out.println("JSON: " + json); User u2 = gson.fromJson(json, User.class); System.out.println("恢復: " + u2); // ==================== 2. List 集合 ==================== System.out.println("\n=== 2. List ==="); List<User> list1 = new ArrayList<>(); for (int i = 0; i < 3; i++) list1.add(new User("如花", 10 + i, new StringBuffer("男"), false)); json = gson.toJson(list1); System.out.println("JSON: " + json); List<User> list2 = gson.fromJson(json, new TypeToken<List<User>>(){}.getType()); System.out.println("恢復: " + list2); // ==================== 3. 陣列 ==================== System.out.println("\n=== 3. Array ==="); User[] arr1 = new User[3]; for (int i = 0; i < 3; i++) arr1[i] = new User("芙蓉", 20, new StringBuffer("人妖"), true); json = gson.toJson(arr1); System.out.println("JSON: " + json); User[] arr2 = gson.fromJson(json, new TypeToken<User[]>(){}.getType()); System.out.println("恢復: " + Arrays.toString(arr2)); // ==================== 4. Map ==================== System.out.println("\n=== 4. Map ==="); Map<String, User> map1 = new LinkedHashMap<>(); for (int i = 0; i < 3; i++) map1.put(String.valueOf(i + 10), arr1[i]); json = gson.toJson(map1); System.out.println("JSON: " + json); Map<String, User> map2 = gson.fromJson(json, new TypeToken<Map<String, User>>(){}.getType()); System.out.println("恢復: " + map2); } } === 1. Bean === JSON: {"name":"鳳姐","age":12,"sex":"未知","isChild":true} 恢復: {name=鳳姐;age=12;sex=未知;isChild=true} === 2. List === JSON: [{"name":"如花","age":10,"sex":"男","isChild":false},{"name":"如花","age":11,"sex":"男","isChild":false},{"name":"如花","age":12,"sex":"男","isChild":false}] 恢復: [{name=如花;age=10;sex=男;isChild=false}, {name=如花;age=11;sex=男;isChild=false}, {name=如花;age=12;sex=男;isChild=false}] === 3. Array === JSON: [{"name":"芙蓉","age":20,"sex":"人妖","isChild":true},{"name":"芙蓉","age":20,"sex":"人妖","isChild":true},{"name":"芙蓉","age":20,"sex":"人妖","isChild":true}] 恢復: [{name=芙蓉;age=20;sex=人妖;isChild=true}, {name=芙蓉;age=20;sex=人妖;isChild=true}, {name=芙蓉;age=20;sex=人妖;isChild=true}] === 4. Map === JSON: {"10":{"name":"芙蓉","age":20,"sex":"人妖","isChild":true},"11":{"name":"芙蓉","age":20,"sex":"人妖","isChild":true},"12":{"name":"芙蓉","age":20,"sex":"人妖","isChild":true}} 恢復: {10={name=芙蓉;age=20;sex=人妖;isChild=true}, 11={name=芙蓉;age=20;sex=人妖;isChild=true}, 12={name=芙蓉;age=20;sex=人妖;isChild=true}} | 觀察點 | 結論 |
|---|---|
| StringBuffer 序列化 | Gson 自動調用 toString() 序列化為字符串,反序列化時直接設為 String 欄位 (若實體欄位為 StringBuffer 會報錯,建議實體統一用 String) |
| Boolean 序列化 | 輸出 true/false (小寫),標準 JSON 格式 |
| Map Key 順序 | 使用 LinkedHashMap 保證輸出順序與插入順序一致 |
| TypeToken 寫法 | new TypeToken<List<User>>(){}.getType() 匿名內部類捕獲泛型 |
| 陣列反序列化 | new TypeToken<User[]>(){}.getType() 同理適用 |
public class AdvancedUser { @SerializedName("user_name") // JSON Key 重命名 private String name; @Expose(serialize = false, deserialize = false) // 完全忽略 private String password; private LocalDateTime createTime; private BigDecimal balance; private Status status; // enum // GsonBuilder 配置 Gson gson = new GsonBuilder() .setDateFormat("yyyy-MM-dd HH:mm:ss") // 日期格式 .registerTypeAdapter(BigDecimal.class, new TypeAdapter<BigDecimal>() { @Override public void write(JsonWriter out, BigDecimal v) throws IOException { out.value(v.stripTrailingZeros().toPlainString()); } @Override public BigDecimal read(JsonReader in) throws IOException { return new BigDecimal(in.nextString()); } }) .excludeFieldsWithoutExposeAnnotation() // 僅序列化 @Expose 欄位 .create(); Gson 處理 Java 對象與 JSON 互轉極其強大且直觀:
✅ Bean:gson.toJson(obj) / gson.fromJson(json, Clazz.class)
✅ List/Set:new TypeToken<List<T>>(){}.getType()
✅ Array:new TypeToken<T[]>(){}.getType()
✅ Map:new TypeToken<Map<K, V>>(){}.getType()
✅ 日期/特殊類型:GsonBuilder 註冊 TypeAdapter
✅ 欄位控制:@Expose, @SerializedName, transient
建議將上述測試類納入專案 test 目錄,作為 Gson 使用規範的活文檔。新成員入職跑一次測試,即可掌握團隊 JSON 處理標準。