基于Jackson注解的JSON工具封装与Redis集成实战

基于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 日期格式不生效

问题现象

输出仍为时间戳格式
解决方案

  1. 检查是否注册JavaTimeModule
  2. 确认时区配置正确
  3. 验证注解pattern拼写

6.2 字段重名冲突

问题现象

多个字段映射到同一JSON属性
解决方案

java 复制代码
public class Order {
    @JsonProperty("contact_phone")
    private String phone; // 映射为contact_phone
    
    @JsonAlias({"phone", "mobile"}) // 兼容多个反序列化字段名
    private String contactPhone;
}

相关推荐
Aska_Lv9 分钟前
线上问题-服务又又又又掉线了,有人要倒霉了
后端
这里有鱼汤9 分钟前
祭出Cython大招后,算法速度让同事以为我偷偷换了Go
后端·python
这里有鱼汤11 分钟前
凌晨三点我用Python重写公司远控程序,竟发现实习生埋了后门?
后端·python
爱的叹息18 分钟前
Spring 约定编程案例与示例
java·后端·spring
安然无虞1 小时前
31天Python入门——第17天:初识面向对象
后端·爬虫·python·职场和发展
yuhaiqiang1 小时前
订单交易系统就该这么设计,既优雅又高效
后端
编程、小哥哥2 小时前
spring之添加freemarker模版熏染
java·后端·spring
hong_zc2 小时前
Spring 拦截器与统一功能的处理
java·后端·spring
珹洺3 小时前
C++从入门到实战(十)类和对象(最终部分)static成员,内部类,匿名对象与对象拷贝时的编译器优化详解
java·数据结构·c++·redis·后端·算法·链表
ai大师4 小时前
给聊天机器人装“短期记忆“:Flask版实现指南
后端·python·gpt·flask·oneapi·中转api·apikey