震驚!50% 的 Java 程序員都不知道的 Jackson 高階用法(含工具類封裝)
在當下的 Java 開發中,JSON 數據處理已經成為繞不開的核心技能。無論是 Web API、微服務通信,還是前后端交互,JSON 都是事實上的通用標準。
在眾多 JSON 解析框架中,Jackson 以性能優越、功能完備、生態豐富而脫穎而出,幾乎成為企業級 Java 項目的首選工具。
但很多開發者對 Jackson 的使用仍停留在最基本的“對象與 JSON 字符串互轉”。事實上,Jackson 提供了大量高級特性,能夠幫助我們處理復雜業務場景,例如:
- 統一日期格式
- 處理嵌套對象與集合
- 動態字段過濾
- 操作 JSON 樹模型
本文將基于實際開發場景,逐步解析 Jackson 的高階用法,并給出一個經過封裝的 工具類 JacksonUtils,幫助你在日常開發中高效、優雅地處理 JSON 數據。
典型場景與解決方案
場景一:復雜對象的序列化與反序列化
需求:將 Java 對象轉為 JSON 字符串,或從 JSON 恢復成 Java 對象。方案:使用 ObjectMapper,并結合注解控制序列化行為。
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
// 對象轉 JSON
String json = mapper.writeValueAsString(user);
// JSON 轉對象
User user = mapper.readValue(json, User.class);場景二:統一日期格式
需求:保證 JSON 中的日期字段格式統一,支持 java.util.Date 與 java.time.LocalDateTime。方案:注冊 JavaTimeModule 并指定格式化規則。
package com.icoderoad.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class JacksonUtils {
private static final ObjectMapper mapper;
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
static {
mapper = new ObjectMapper();
JavaTimeModule timeModule = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
mapper.registerModule(timeModule);
}
public static String toJsonWithFormat(Object obj) {
try {
return mapper.writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException("日期格式化失敗", e);
}
}
}場景三:嵌套對象與集合處理
需求:解析包含復雜嵌套結構的 JSON(如訂單、商品、分類)。方案:借助 TypeReference 處理泛型集合。
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.List;
import java.util.Map;
class Order {
private String orderId;
private List<Product> products;
private Map<String, Object> extraInfo;
}
class Product {
private String productId;
private String name;
private double price;
}
public class JacksonUtils {
public static <T> List<T> toList(String json, Class<T> elementClass) {
try {
return mapper.readValue(json,
mapper.getTypeFactory().constructCollectionType(List.class, elementClass));
} catch (Exception e) {
throw new RuntimeException("JSON 轉 List 失敗", e);
}
}
public static <T> T toComplexObject(String json, TypeReference<T> typeReference) {
try {
return mapper.readValue(json, typeReference);
} catch (Exception e) {
throw new RuntimeException("JSON 轉復雜對象失敗", e);
}
}
}場景四:動態字段過濾
需求:根據業務場景動態控制字段序列化(如隱藏敏感信息)。方案:使用 @JsonFilter 配合 SimpleFilterProvider。
import com.fasterxml.jackson.annotation.JsonFilter;
@JsonFilter("userFilter")
class User {
private String userId;
private String username;
private String password; // 敏感字段
private String email;
}
public class JacksonUtils {
public static String toJsonWithFilter(Object obj, String filterName, String... fieldsToExclude) {
try {
var filters = new com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider()
.addFilter(filterName,
com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter.serializeAllExcept(fieldsToExclude));
return mapper.writer(filters).writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException("字段過濾失敗", e);
}
}
}場景五:JSON 樹模型操作
需求:直接操作 JSON 數據節點,支持動態新增、修改、刪除字段。方案:使用 JsonNode 與 ObjectNode。
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class JacksonUtils {
public static JsonNode toJsonNode(String json) {
try {
return mapper.readTree(json);
} catch (Exception e) {
throw new RuntimeException("JSON 轉 JsonNode 失敗", e);
}
}
public static String modifyNode(String json, String fieldName, Object newValue) {
try {
ObjectNode node = (ObjectNode) mapper.readTree(json);
node.putPOJO(fieldName, newValue);
return node.toString();
} catch (Exception e) {
throw new RuntimeException("修改 JSON 節點失敗", e);
}
}
}完整工具類封裝
結合以上所有功能,我們封裝了一個通用的 JacksonUtils 工具類,位于路徑:
/src/main/java/com/icoderoad/utils/JacksonUtils.java它提供:
- 對象與 JSON 的互轉
- 日期統一處理
- 集合與復雜嵌套結構解析
- 動態字段過濾
- JSON 樹模型操作
package com.icoderoad.utils;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* Jackson JSON 工具類
* 提供對象-JSON 轉換、日期格式化、集合解析、字段過濾、樹模型操作等功能
*/
public class JacksonUtils {
private static final ObjectMapper mapper;
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
static {
mapper = new ObjectMapper();
// 序列化時忽略 null 字段
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 反序列化時忽略未知字段
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 配置 Java 8 時間模塊
JavaTimeModule timeModule = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
mapper.registerModule(timeModule);
}
/** 對象轉 JSON 字符串 */
public static String toJson(Object obj) {
try {
return mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException("對象轉 JSON 失敗", e);
}
}
/** JSON 字符串轉對象 */
public static <T> T toObject(String json, Class<T> clazz) {
try {
return mapper.readValue(json, clazz);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON 轉對象失敗", e);
}
}
/** JSON 轉 List */
public static <T> List<T> toList(String json, Class<T> elementClass) {
try {
return mapper.readValue(json,
mapper.getTypeFactory().constructCollectionType(List.class, elementClass));
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON 轉 List 失敗", e);
}
}
/** JSON 轉復雜對象(如 Map、嵌套結構) */
public static <T> T toComplexObject(String json, TypeReference<T> typeReference) {
try {
return mapper.readValue(json, typeReference);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON 轉復雜對象失敗", e);
}
}
/** 指定過濾字段進行序列化 */
public static String toJsonWithFilter(Object obj, String filterName, String... fieldsToExclude) {
try {
FilterProvider filters = new SimpleFilterProvider()
.addFilter(filterName, SimpleBeanPropertyFilter.serializeAllExcept(fieldsToExclude));
return mapper.writer(filters).writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON 序列化字段過濾失敗", e);
}
}
/** JSON 轉 JsonNode */
public static JsonNode toJsonNode(String json) {
try {
return mapper.readTree(json);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON 轉 JsonNode 失敗", e);
}
}
/** 獲取 JsonNode 中指定字段值 */
public static String getNodeValue(JsonNode node, String fieldName) {
JsonNode valueNode = node.get(fieldName);
return valueNode != null ? valueNode.asText() : null;
}
/** 修改 JSON 中指定字段 */
public static String modifyNode(String json, String fieldName, Object newValue) {
try {
ObjectNode node = (ObjectNode) mapper.readTree(json);
if (newValue instanceof String) {
node.put(fieldName, (String) newValue);
} else if (newValue instanceof Integer) {
node.put(fieldName, (Integer) newValue);
} else if (newValue instanceof Boolean) {
node.put(fieldName, (Boolean) newValue);
} else if (newValue instanceof Double) {
node.put(fieldName, (Double) newValue);
} else {
node.putPOJO(fieldName, newValue);
}
return node.toString();
} catch (JsonProcessingException e) {
throw new RuntimeException("修改 JSON 節點失敗", e);
}
}
}最佳實踐建議
- 單例模式:
ObjectMapper是線程安全的,應全局復用。 - 異常處理:工具類中統一封裝異常,避免業務代碼重復 try-catch。
- 統一日期:推薦使用 Java 8 的
LocalDateTime,避免Date的線程安全問題。 - 字段控制:通過注解和過濾器靈活控制 JSON 輸出。
- 性能優化:大數據量場景下可考慮 Jackson Streaming API (
JsonParser/JsonGenerator)。
結語
掌握 Jackson 不僅僅是學會“對象和 JSON 的互轉”,而是要善用其豐富的生態與擴展能力。
通過本文的工具類與實戰案例,你可以:
- 高效應對各種 JSON 場景
- 統一團隊代碼風格
- 顯著提升開發效率與代碼質量
Jackson 的功能遠不止于此,建議在實踐中結合官方文檔深入探索,例如多態序列化、自定義模塊、性能調優等,能讓你的 JSON 處理能力更上一層樓。



























