基于Jackson注解的JSON工具封装与Redis集成实战
一、深度整合Jackson注解的领域对象
1.1 完整商品类示例
java
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL) // 空值字段不序列化
public class Product {
@JsonProperty("product_id") // 自定义JSON字段名
private Long id;
@JsonProperty("product_name")
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING) // 精确序列化BigDecimal
private BigDecimal price;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private LocalDateTime createTime;
@JsonSerialize(using = CustomListSerializer.class) // 自定义列表序列化
private List<String> tags;
@JsonIgnore // 忽略敏感字段
private String internalCode;
// 构造方法、getter、setter省略
}
二、增强型JsonUtil工具类
2.1 支持注解的配置
java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class JsonUtil {
private static final ObjectMapper mapper = new ObjectMapper();
static {
// 基础配置
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 支持注解的配置
mapper.enable(SerializationFeature.INDENT_OUTPUT); // 美化输出
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
// 序列化方法
public static String toJson(Object obj) {
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException("序列化失败", e);
}
}
// 反序列化方法(支持泛型)
public static <T> T fromJson(String json, Class<T> clazz) {
try {
return mapper.readValue(json, clazz);
} catch (Exception e) {
throw new RuntimeException("反序列化失败", e);
}
}
}
2.2 自定义序列化器示例
java
// 处理标签列表的紧凑格式
public class CustomListSerializer extends JsonSerializer<List<String>> {
@Override
public void serialize(List<String> value, JsonGenerator gen,
SerializerProvider serializers) throws IOException {
gen.writeString(String.join(",", value));
}
}
三、Redis集成与验证
3.1 Redis配置类增强
java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
// 启用事务支持
template.setEnableTransactionSupport(true);
return template;
}
}
3.2 存储与读取验证
java
// 测试用例
@Test
void testProductSerialization() {
Product product = new Product();
product.setId(1001L);
product.setName("iPad Pro");
product.setPrice(new BigDecimal("7999.00"));
product.setCreateTime(LocalDateTime.now());
product.setTags(List.of("平板", "旗舰"));
// 序列化
String json = JsonUtil.toJson(product);
System.out.println("序列化结果:\n" + json);
// 存储到Redis
redisTemplate.opsForValue().set("product:1001", json);
// 从Redis读取并反序列化
String storedJson = redisTemplate.opsForValue().get("product:1001");
Product parsedProduct = JsonUtil.fromJson(storedJson, Product.class);
assertNotNull(parsedProduct);
assertEquals("iPad Pro", parsedProduct.getName());
}
序列化输出示例:
json
{
"product_id" : 1001,
"product_name" : "iPad Pro",
"price" : "7999.00",
"createTime" : "2023-08-20 14:30:45",
"tags" : "平板,旗舰"
}
四、注解应用场景详解
4.1 日期格式控制矩阵
需求场景 | 注解配置 | 输出示例 |
---|---|---|
日期+时间 | @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") |
"2023-08-20 14:30:45" |
仅日期 | @JsonFormat(pattern="yyyy-MM-dd") |
"2023-08-20" |
时间戳格式 | 不添加注解(默认配置) | 1692592245 |
ISO8601格式 | @JsonFormat(shape=JsonFormat.Shape.STRING) |
"2023-08-20T14:30:45.123+08:00" |
4.2 字段重命名策略
java
// 全局配置驼峰转下划线
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
// 配合字段级注解
public class User {
@JsonProperty("user_name") // 优先级高于全局策略
private String userName;
private String emailAddress; // 自动转为email_address
}
五、生产环境最佳实践
5.1 安全防护方案
java
// 防止Jackson反序列化漏洞
mapper.enable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 配置反序列化白名单
SimpleModule module = new SimpleModule();
module.addDeserializer(Product.class, new SafeProductDeserializer());
mapper.registerModule(module);
5.2 性能优化技巧
java
// 复用ObjectWriter实例
private static final ObjectWriter productWriter = mapper.writerFor(Product.class);
public static String toJsonFast(Product product) {
try {
return productWriter.writeValueAsString(product);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
// 使用缓冲池提升性能
public static final ObjectMapper sharedMapper = new ObjectMapper();
private static final ObjectWriter sharedWriter = sharedMapper.writer();
六、常见问题解决方案
6.1 日期格式不生效
问题现象 :
输出仍为时间戳格式
解决方案:
- 检查是否注册JavaTimeModule
- 确认时区配置正确
- 验证注解pattern拼写
6.2 字段重名冲突
问题现象 :
多个字段映射到同一JSON属性
解决方案:
java
public class Order {
@JsonProperty("contact_phone")
private String phone; // 映射为contact_phone
@JsonAlias({"phone", "mobile"}) // 兼容多个反序列化字段名
private String contactPhone;
}