在现代 Java 开发中,JSON 处理是一项基础且关键的技能。Jackson 作为业界领先的 JSON 处理库,凭借其高性能、灵活性和丰富的特性,成为了大多数 Java 项目的首选。本文将结合实际场景,深入讲解 Jackson 的实战应用,并提供一个封装完善的工具类,帮助你高效处理 JSON 数据。
一、典型应用场景与解决方案
场景 1:复杂对象的序列化与反序列化
需求:将 Java 对象转换为 JSON 字符串,或从 JSON 字符串还原为 Java 对象。
解决方案:使用 Jackson 的ObjectMapper进行基础转换,通过注解控制序列化行为。
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.LocalDateTime;
// 用户类示例
@JsonInclude(JsonInclude.Include.NON_NULL) // 忽略null字段
class User {
@JsonProperty("user_id") // 自定义JSON字段名
private String userId;
private String username;
private LocalDateTime createTime;
// 构造方法、Getter和Setter略
}
// 工具类方法
public class JacksonUtils {
private static final ObjectMapper mapper = new ObjectMapper();
// 对象转JSON字符串
public static String toJson(Object obj) {
try {
return mapper.writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException("JSON序列化失败", e);
}
}
// JSON字符串转对象
public static <T> T toObject(String json, Class<T> clazz) {
try {
return mapper.readValue(json, clazz);
} catch (Exception e) {
throw new RuntimeException("JSON反序列化失败", e);
}
}
}
// 使用示例
User user = new User("1001", "john_doe", LocalDateTime.now());
String json = JacksonUtils.toJson(user);
User parsedUser = JacksonUtils.toObject(json, User.class);
场景 2:处理日期格式
需求:统一 JSON 中的日期格式,支持多种日期类型(如java.util.Date、java.time.LocalDateTime)。
解决方案:注册 JavaTimeModule 并配置日期格式化。
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();
// 配置Java 8日期时间模块
JavaTimeModule timeModule = new JavaTimeModule();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
// 注册LocalDateTime序列化器和反序列化器
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
mapper.registerModule(timeModule);
}
// 新增支持日期格式化的转换方法
public static String toJsonWithFormat(Object obj) {
return toJson(obj); // 使用已配置的mapper
}
}
场景 3:处理嵌套对象与集合
需求:处理包含复杂嵌套结构的 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;
// 构造方法、Getter和Setter略
}
// 商品类示例
class Product {
private String productId;
private String name;
private double price;
// 构造方法、Getter和Setter略
}
public class JacksonUtils {
// 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 (Exception 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 (Exception e) {
throw new RuntimeException("JSON转复杂对象失败", e);
}
}
}
// 使用示例
String jsonList = "[{"productId":"P001","name":"iPhone","price":9999.0}]";
List<Product> productList = JacksonUtils.toList(jsonList, Product.class);
// 处理复杂嵌套结构
TypeReference<Map<String, List<Order>>> typeRef = new TypeReference<>() {};
Map<String, List<Order>> resultMap = JacksonUtils.toComplexObject(jsonString, typeRef);
场景 4:动态过滤字段
需求:根据不同场景,动态控制哪些字段需要序列化或反序列化(如敏感信息过滤)。
解决方案:使用@JsonFilter注解和SimpleFilterProvider。
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
// 用户类添加过滤器注解
@JsonFilter("userFilter")
class User {
private String userId;
private String username;
private String password; // 敏感字段
private String email;
// 构造方法、Getter和Setter略
}
public class JacksonUtils {
// 过滤指定字段
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 (Exception e) {
throw new RuntimeException("带过滤的JSON序列化失败", e);
}
}
}
// 使用示例:过滤密码字段
User user = new User("1001", "john_doe", "123456", "john@example.com");
String safeJson = JacksonUtils.toJsonWithFilter(user, "userFilter", "password");
场景 5:处理 JSON 树模型
需求:直接操作 JSON 数据结构,动态增删改查节点。
解决方案:使用 Jackson 的树模型 API(JsonNode)。
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class JacksonUtils {
// 解析JSON字符串为JsonNode
public static JsonNode toJsonNode(String json) {
try {
return mapper.readTree(json);
} catch (Exception 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;
}
// 修改JsonNode并转换为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);
} // 其他类型可扩展
return node.toString();
} catch (Exception e) {
throw new RuntimeException("修改JSON节点失败", e);
}
}
}
// 使用示例
String json = "{"name":"Alice","age":30}";
JsonNode node = JacksonUtils.toJsonNode(json);
String name = JacksonUtils.getNodeValue(node, "name"); // "Alice"
String modifiedJson = JacksonUtils.modifyNode(json, "age", 31);
二、完整工具类封装
下面是一个完整的 Jackson 工具类,集成了上述所有功能:
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.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;
import java.util.Map;
/**
* 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 {
// 初始化ObjectMapper
mapper = new ObjectMapper();
// 配置序列化选项
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略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;
}
/**
* 修改JsonNode并转换为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 日期时间 API,避免java.util.Date的线程安全问题。
- 字段控制:通过注解(如@JsonInclude)和过滤器动态控制序列化行为。
- 性能优化:大量数据处理时,考虑使用 Jackson 的流式 API(JsonParser/JsonGenerator)。
通过这个工具类和实战方案,你可以轻松应对日常开发中的各种 JSON 处理需求,提高代码质量和开发效率。Jackson 的强大远不止于此,建议深入研究其官方文档,探索更多高级特性