JSON 已成微服務、前後端分離、配置管理的事實標準。Java 生態擁有多個成熟庫,本文對比四大主流庫,詳細演示 Json-lib(文中使用)核心用法,並給出 2024 年技術選型建議。
| 庫 | Maven 坐標 | 特點 | 適用場景 |
|---|---|---|---|
| Jackson | com.fasterxml.jackson.core:jackson-databind | 效能最優、功能最全、Spring Boot 默認、支援 Kotlin/Scala、模組化擴展 | 首選:高性能、企業級、微服務 |
| Gson | com.google.code.gson:gson | API 簡潔、Google 維護、流式/樹模型雙支援、對 Kotlin data class 友好 | Android、中小專案、簡單序列化需求 |
| JSON-B (Jakarta EE) | jakarta.json.bind:jakarta.json.bind-api + 實現 | 標準化註解 (@JsonbProperty)、CDI 整合、可移植 | Jakarta EE / MicroProfile 專案 |
| json-lib (舊版) | net.sf.json-lib:json-lib | 早期流行、依賴多 (ezmorph, xom 等)、不再維護、效能較弱 | 僅維護舊專案 |
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
// 1. 集合/陣列 → JSONArray
List<String> list = List.of("first", "second");
JSONArray jsonArray = JSONArray.fromObject(list); // ["first","second"]
// 2. Map/Bean → JSONObject
Map<String, Object> map = Map.of(
"name", "JSON", "bool", true, "int", 1, "arr", new String[]{"a","b"}
);
JSONObject jsonObject = JSONObject.fromObject(map);
// {"name":"JSON","bool":true,"int":1,"arr":["a","b"]}
// 3. JSON → Java 對象 (需註冊類映射)
JSONObject json = JSONObject.fromObject("{\"name\":\"JSON\",\"age\":25}");
User user = (User) JSONObject.toBean(json, User.class); // 需 User 有無參構造器 + setter
// 4. 陣列轉 List<Bean>
JSONArray array = JSONArray.fromObject("[{\"id\":1},{\"id\":2}]");
List<User> users = (List<User>) JSONArray.toCollection(array, User.class);
XMLSerializer 雙向轉換| 問題 | 原因 | 解法 |
|---|---|---|
| 日期序列化為長整數 | 默認輸出 time in millis | JsonConfig.setJsonPropertyFilter 或註冊 JsonValueProcessor 格式化 |
| 循環引用堆疊溢出 | 雙向關聯 (Parent↔Child) | JsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT) |
| Enum 序列化為名稱而非值 | 默認行為 | 實現 JsonBeanProcessor 或改用 Jackson @JsonValue |
| 大數字精度丟失 | 用 Double 存儲 | 改用 BigDecimal + JsonConfig.registerJsonValueProcessor |
| 中文輸出為 \uXXXX | 默認確保 ASCII | JsonConfig.setEncoding("UTF-8") + 確保輸出流編碼 |
// Jackson 等價代碼 (更簡潔、效能更高、類型安全)
ObjectMapper mapper = new ObjectMapper()
.registerModule(new JavaTimeModule()) // Java 8 日期時間支援
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 序列化
String json = mapper.writeValueAsString(userList);
// 反序列化 (類型安全,無需強轉)
List<User> users = mapper.readValue(json, new TypeReference<List<User>>() {});
// 處理循環引用
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
json-lib 完成了歷史使命。新專案無理由不選 Jackson:生態最完善、效能標桿、Spring 生態原生整合、持續活躍維護。維舊專案時,掌握上述避坑點可平穩過渡;重構窗口期到來時,全量遷移 Jackson 是技術債清償的高收益動作。