【实战应用】序列化/反序列化

背景:

最近在做chatAI聊天机器人时,遇到了序列化的问题。需要把用户输入的数据序列化为json数据存储在Redis中实现连续上下文对话。


- 序列化:对象 ➜ JSON / 字节,方便存储、传输
- 反序列化:JSON ➜ 对象,还原状态

序列化:

话不多说,上代码:

user是用户的名称,userInput是用户输入的数据。new MessageDTO 把数据存储到类对象中。

getHistory()他是调用了另一个反序列化的方法,稍后讲。

public List<Message> appendUserMessage(String userInput) {
        MessageDTO dto = new MessageDTO("user", userInput);   // ① 把用户输入封装为 DTO

        //这一步是在存储的时候把JAVA对象通过RedisConfig配置进行序列化
        redisTemplate.opsForList().rightPush(redisKey, dto);  // ② 追加到 Redis 列表右侧
        return getHistory();                                  // ③ 取出当前全部历史,返回给调用方
    }

new MessageDTO类

public class MessageDTO {
    private String role;  // "user" 或 "assistant"
    private String content;

    public MessageDTO() {}
    //全参构造器(写入 Redis 时调用)
    public MessageDTO(String role, String content) {
        this.role = role;
        this.content = content;
    }

    // getter 和 setter
    public String getRole() { return role; }
    public void setRole(String role) { this.role = role; }
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
}

重点是RedisConfig的配置,这部分是配置Redis和Jackson(序列化/反序列化库,通过pom导入)

public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        // 配置Jackson 对象映射器,支持多态序列化
        ObjectMapper objectMapper = new ObjectMapper();
        // 启用类型信息,保证子类反序列化正确
        objectMapper.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY
        );

        //万能型 JSON 序列化器,可以序列化任意对象,反序列化时能根据类型信息恢复原始对象。
        GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(objectMapper);

        // key 采用字符串序列化,防止类型报错
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());

        // value 采用带类型信息的 JSON 序列化
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);

        template.afterPropertiesSet();
        return template;
    }
}
        <!--jackson序列化-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

也就是通过Redis和Jackson序列化配置把对象序列化为Json格式存储到Redis中,序列化之后的数据大概是:

{
  "@class": "com.universal.main.controller.chatAi.MessageDTO",
  "role": "user",
  "content": "你好,爱蜜莉雅~"
}

以上就是序列化过程

反序列化:

没错回到刚才第一步getHistory()的方法:

    public List<Message> getHistory() {
        // ① 读出整个列表,Spring Redis (配置了Jackson)自动地把 Redis 中的 JSON 数据 反序列化为 Java 对象(Object).
        List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);
        if (list == null) return List.of();                                     // 空则返回空列表
        //封装为 Spring AI 框架所需要的标准对象
        return list.stream().map(o -> {                                         // ② 逐条转换
            if (!(o instanceof MessageDTO)) {
                throw new IllegalStateException("缓存数据格式错误,期望 MessageDTO,但实际是:" + o.getClass());
            }
            MessageDTO dto = (MessageDTO) o;
            return "user".equals(dto.getRole())                                  // ③ 依据 role 决定类型
                    ? new UserMessage(dto.getContent())
                    : new AssistantMessage(dto.getContent());
        }).collect(Collectors.toList());                                         // ④ 返回 List<Message>
    }

重点是:List<Object> list = redisTemplate.opsForList().range(redisKey, 0, -1);

因为之前在RedisConfig中配置了Jackson,它会在调用range范围读取时自动地把 Redis 中的 JSON 数据 反序列化为 Java 对象(Object).

下面部分的是为了封装为 Spring AI 框架所需要的标准对象,不用在意。

好了,以上就是反序列化和序列化的实例应用,我们可以借助Jackson简单的就能实现序列化和反序列化。希望能帮助大家!

其他:

一些序列化反序列化的常用场景: Redis 缓存、接口传参、微服务通信、消息队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值