# Spring Boot Jackson 常用功能與使用方法 在 Spring Boot 中,**Jackson** 是最常用的 JSON 解析與序列化/反序列化工具,Spring Boot 內建支援 Jackson,並透過 `spring-boot-starter-json` 依賴自動配置。 本文將介紹一些 **常用、重要** 的 Jackson 功能,包含使用情境與範例。 --- ## 1. 控制 JSON 字段 **情境**: 只想讓某些字段被序列化/反序列化,例如隱藏密碼。 **解法**: 使用 `@JsonIgnore` 或 `@JsonProperty` ### 範例 ```java import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; public class User { private String username; @JsonIgnore // 這個字段不會被序列化到 JSON private String password; @JsonProperty("full_name") // 變更 JSON 字段名稱 private String fullName; // Getter / Setter } ``` ### 輸出 JSON ```json { "full_name": "John Doe", "username": "johndoe" } ``` (不會輸出 password 欄位) --- ## 2. 日期格式化 **情境**: Java 內的 LocalDateTime 無法直接被 JSON 處理,想要格式化日期。 **解法**: 使用 `@JsonFormat` ### 範例 ```java import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDateTime; public class Event { private String name; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime eventDate; // Constructor, Getter / Setter } ``` ### 輸出 JSON ```json { "name": "Spring Boot Workshop", "eventDate": "2025-03-17 10:30:00" } ``` --- ## 3. 忽略 NULL 值 **情境**: JSON 回應時不想顯示 null 值,讓 JSON 更乾淨。 **解法**: `@JsonInclude(JsonInclude.Include.NON_NULL)` ### 範例 ```java import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_NULL) public class Product { private String name; private Double price; // 如果 price 為 null,則不會輸出 JSON // Constructor, Getter / Setter } ``` ### 輸出 JSON ```json { "name": "Laptop" } ``` (當 price = null 時,price 欄位不會出現在 JSON 中) --- ## 4. 自訂 JSON 序列化與反序列化 **情境**: 需要客製化物件的轉換邏輯,例如 Boolean 轉換為 Yes/No。 **解法**: 自訂 `JsonSerializer` 和 `JsonDeserializer` ### 自訂 Boolean 序列化 ```java import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; public class BooleanToYesNoSerializer extends JsonSerializer<Boolean> { @Override public void serialize(Boolean value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeString(value ? "Yes" : "No"); } } ``` ### 應用在 Model ```java import com.fasterxml.jackson.databind.annotation.JsonSerialize; public class UserPreference { private String username; @JsonSerialize(using = BooleanToYesNoSerializer.class) private Boolean notificationsEnabled; // Constructor, Getter / Setter } ``` ### 輸出 JSON ```json { "username": "johndoe", "notificationsEnabled": "Yes" } ``` --- ## 5. 全域日期格式設定 **情境**: 想要讓整個應用程式的日期格式統一,不用每個類別都加 `@JsonFormat`。 **解法**: 自訂 `ObjectMapper` ### 設定 ```java import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.text.SimpleDateFormat; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); // 支援 Java 8 日期時間 objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); return objectMapper; } } ``` 這樣所有 `Date` 或 `LocalDateTime` 物件都會輸出成 "yyyy-MM-dd HH:mm:ss" 格式。 --- ## 6. 全域忽略未知字段 **情境**: 當 JSON 傳入額外字段時,不想讓 `ObjectMapper` 解析時拋出錯誤。 **解法**: `@JsonIgnoreProperties(ignoreUnknown = true)` ### 範例 ```java import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class Person { private String name; private int age; // Constructor, Getter / Setter } ``` ### JSON 輸入 ```json { "name": "Alice", "age": 25, "extraField": "Should be ignored" } ``` 即使 `extraField` 在 `Person` 類別內沒有定義,仍可正常解析,不會拋出 `UnrecognizedPropertyException`。 --- ## 7. 啟用 JSON Pretty Print **情境**: 想讓 JSON 變得更好閱讀(美化格式)。 **解法**: 使用 `SerializationFeature.INDENT_OUTPUT` ### 範例 ```java import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; public class JsonPrettyPrintExample { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enable(SerializationFeature.INDENT_OUTPUT); User user = new User("johndoe", "John Doe"); String json = objectMapper.writeValueAsString(user); System.out.println(json); } } ``` ### 輸出 JSON ```json { "username": "johndoe", "full_name": "John Doe" } ``` (格式化 JSON 輸出,方便閱讀) --- ## 8. 使用 `ObjectMapper` 進行類別轉換 **情境**: 在不同的類別之間進行轉換,例如從 `Entity` 轉換為 `DTO`。 ### **1. 類別轉換** ```java import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonMapperExample { public static void main(String[] args) { ObjectMapper objectMapper = new ObjectMapper(); UserEntity entity = new UserEntity(1L, "johndoe", "John Doe", "password123"); UserDTO dto = objectMapper.convertValue(entity, UserDTO.class); System.out.println(dto); } } ``` ### **9. List 轉換** ```java import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Arrays; import java.util.List; public class JacksonListMapperExample { public static void main(String[] args) { ObjectMapper objectMapper = new ObjectMapper(); List<UserEntity> entityList = Arrays.asList( new UserEntity(1L, "johndoe", "John Doe", "password123"), new UserEntity(2L, "janedoe", "Jane Doe", "password456") ); List<UserDTO> dtoList = objectMapper.convertValue(entityList, new TypeReference<List<UserDTO>>() {}); dtoList.forEach(System.out::println); } } ``` ### **10. JSON 轉換為 Class** ```java import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Map; public class JsonToClassExample { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); // JSON 字串 String json = "{\"id\":3, \"username\":\"alice\", \"fullName\":\"Alice Wonderland\"}"; // 先轉換為 Map Map<String, Object> map = objectMapper.readValue(json, Map.class); // 再轉換為 UserDTO UserDTO dto = objectMapper.convertValue(map, UserDTO.class); System.out.println(dto); } } ``` ### **輸出結果** ```json { "id": 3, "username": "alice", "fullName": "Alice Wonderland" } ``` --- ## 結論 Spring Boot 內建 Jackson 並提供許多強大的功能,讓我們可以輕鬆地: ✅ 控制 JSON 字段(@JsonIgnore, @JsonProperty) ✅ 格式化日期(@JsonFormat) ✅ 忽略 null 值(@JsonInclude) ✅ 自訂序列化/反序列化 ✅ 全域日期設定(ObjectMapper) ✅ 忽略未知字段(@JsonIgnoreProperties) ✅ 啟用 JSON 美化輸出 ✅ 使用 ObjectMapper 進行類別轉換 這些技巧在開發 API 時都很實用,可以根據不同需求選擇適合的方式! 🚀 ###### tags: `Java` `Spring Boot` `Jackson` `JSON` `序列化` `反序列化` `日期格式化` `自訂序列化` `全域設定` `忽略未知字段` `美化輸出` `ObjectMapper` `類別轉換` `List 轉換` `JSON 轉換`