JSON 已成為微服務、前後端分離、配置中心的通用數據交換格式。Java 生態中主流三大庫——Jackson(Spring Boot 默認)、Gson(Google 出品)、json-lib(老牌、已停更)——各有優劣。本文以實戰代碼對比序列化/反序列化、泛型集合、日期、Null 處理、性能等核心維度,給出選型建議與避坑指南。
<!-- Jackson (推薦) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
<!-- Gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- json-lib (不推薦新項目) -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- 需額外 5 個傳遞依賴:commons-beanutils/collections/lang/logging, ezmorph -->
| 場景 | Jackson | Gson | json-lib |
|---|---|---|---|
| 對象 → JSON | mapper.writeValueAsString(obj) | gson.toJson(obj) | JSONObject.fromObject(obj).toString() |
| JSON → 對象 | mapper.readValue(json, clazz) | gson.fromJson(json, clazz) | (T)JSONObject.toBean(jsonObj, clazz) |
| List → JSON | 原生支持 | 原生支持 | 需用 JSONArray.fromObject(list) |
| JSON → List<T> | mapper.readValue(json, new TypeReference<List<T>>(){}) | gson.fromJson(json, new TypeToken<List<T>>(){}.getType()) | JSONArray.toList(jsonArr, clazz) |
| Map → JSON | 原生支持 | 原生支持 | JSONObject.fromObject(map) |
| 日期格式化 | 註解 @JsonFormat(pattern="yyyy-MM-dd") 或全局配置 | gsonBuilder.setDateFormat("yyyy-MM-dd") | 需自定義 JsonValueProcessor |
| Null 值處理 | mapper.setSerializationInclusion(Include.NON_NULL) | gsonBuilder.serializeNulls() (默認不序列化 null) | 默認輸出 null |
| 字段命名策略 | PropertyNamingStrategies.SNAKE_CASE | FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES | 不支持,需手動映射 |
| 註解驅動 | 豐富 (@JsonProperty, @JsonIgnore, @JsonAlias...) | 中等 (@SerializedName, @Expose) | 無,靠 JavaBean 約定 |
// 實體類
@Data @AllArgsConstructor @NoArgsConstructor
public class User {
private Long id;
private String username;
private LocalDateTime createTime;
private List<String> roles;
private Map<String, Object> extInfo;
}
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule()); // 支持 Java 8 時間類型
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 對象 → JSON
String json = mapper.writeValueAsString(user);
// {"id":1,"username":"zhangsan","createTime":"2024-01-15T10:30:00","roles":["admin","user"],"extInfo":{"dept":"RD"}}
// JSON → 對象
User u = mapper.readValue(json, User.class);
// 泛型集合
List<User> list = mapper.readValue(jsonArray, new TypeReference<List<User>>(){});
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
String json = gson.toJson(user);
User u = gson.fromJson(json, User.class);
List<User> list = gson.fromJson(jsonArray, new TypeToken<List<User>>(){}.getType());
// 需要預先註冊 Morpher 處理日期等
MorpherRegistry registry = new MorpherRegistry();
registry.registerMorpher(new DateMorpher(new String[]{"yyyy-MM-dd HH:mm:ss"}));
MorpherRegistry.setDefaultMorpherRegistry(registry);
JSONObject jsonObj = JSONObject.fromObject(user);
String json = jsonObj.toString();
User u = (User) JSONObject.toBean(jsonObj, User.class);
| 操作 | Jackson | Gson | json-lib |
|---|---|---|---|
| 序列化 (對象→JSON) | ~0.8 ms/op | ~1.1 ms/op | ~2.5 ms/op |
| 反序列化 (JSON→對象) | ~1.2 ms/op | ~1.5 ms/op | ~3.8 ms/op |
數據僅供相對參考,實際受對象複雜度、JVM 預熱、GC 影響。Jackson 在流式處理、大對象、後處理器擴展上優勢明顯。
新項目 / Spring Boot 整合
│
├─ 需要高性能、流式 API、豐富註解、模塊化擴展 → Jackson (首選)
│
├─ 輕量級、無依賴、API 極簡、Android 友好 → Gson
│
└─ 維護 10 年前 legacy 項目、無法升級依賴 → json-lib (被動選擇)
ObjectMapper 單例(線程安全),避免重複創建開銷FAIL_ON_UNKNOWN_PROPERTIES = false,兼容 API 版本演進LocalDateTime + JavaTimeModule,棄用 java.util.Date@JsonIgnore 或配置過濾器JsonGenerator 流式寫入 / JsonParser 流式讀取,常數內存JsonProcessingException(序列化)與 JsonMappingException(反序列化),便於精準告警Jackson 以生態完善、性能領先、擴展性強成為當前 Java JSON 處理的事實標準。Gson 以輕量、簡潔佔據移動端與簡單場景一席之地。json-lib 已進入維護模式,新項目不建議引入。掌握核心 API、泛型類型擦除應對(TypeReference/TypeToken)、日期與 Null 處理策略,是高效處理 JSON 的關鍵。